blob: 5ed0aee5b14bd5c00e77bc0e705772a61ac8a497 [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
228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
229#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
242#define AFE_PROXY_RECORD_PERIOD_SIZE 768
243#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
juyuchenbe5c67e2018-08-29 17:19:20 +0800543static bool is_supported_24bits_audiosource(audio_source_t source)
544{
545 switch (source) {
546 case AUDIO_SOURCE_UNPROCESSED:
547#ifdef ENABLED_24BITS_CAMCORDER
548 case AUDIO_SOURCE_CAMCORDER:
549#endif
550 return true;
551 default:
552 break;
553 }
554 return false;
555}
556
Haynes Mathew George03c40102016-01-29 17:57:48 -0800557static inline bool is_mmap_usecase(audio_usecase_t uc_id)
558{
559 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
560 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
561}
562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700563static int get_snd_codec_id(audio_format_t format)
564{
565 int id = 0;
566
Eric Laurent8251ac82014-07-23 11:00:25 -0700567 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 case AUDIO_FORMAT_MP3:
569 id = SND_AUDIOCODEC_MP3;
570 break;
571 case AUDIO_FORMAT_AAC:
572 id = SND_AUDIOCODEC_AAC;
573 break;
574 default:
575 ALOGE("%s: Unsupported audio format", __func__);
576 }
577
578 return id;
579}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800580
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800581static int audio_ssr_status(struct audio_device *adev)
582{
583 int ret = 0;
584 struct mixer_ctl *ctl;
585 const char *mixer_ctl_name = "Audio SSR Status";
586
587 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
588 ret = mixer_ctl_get_value(ctl, 0);
589 ALOGD("%s: value: %d", __func__, ret);
590 return ret;
591}
592
vivek mehta4a824772017-06-08 19:05:49 -0700593static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
594{
595 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
596}
597
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800598static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
599{
600 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
601 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
602 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
605 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
606
607}
608
609static bool is_a2dp_device(snd_device_t out_snd_device)
610{
611 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
612}
613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800614int enable_audio_route(struct audio_device *adev,
615 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616{
yixuanjiang509f0a72018-09-06 18:37:23 +0800617 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800618 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800619
620 if (usecase == NULL)
621 return -EINVAL;
622
623 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
624
yixuanjiang509f0a72018-09-06 18:37:23 +0800625 if (usecase->type == PCM_CAPTURE)
626 snd_device = usecase->in_snd_device;
627 else
628 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530629 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800630 audio_extn_utils_send_audio_calibration(adev, usecase);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800631 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800632 platform_add_backend_name(adev->platform, mixer_path, snd_device);
633 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700634 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700635 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800637 ALOGV("%s: exit", __func__);
638 return 0;
639}
640
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800641int disable_audio_route(struct audio_device *adev,
642 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800643{
yixuanjiang509f0a72018-09-06 18:37:23 +0800644 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800645 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
647 if (usecase == NULL)
648 return -EINVAL;
649
650 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800651 if (usecase->type == PCM_CAPTURE)
652 snd_device = usecase->in_snd_device;
653 else
654 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800655 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800656 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700657 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700658 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000659 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800661 ALOGV("%s: exit", __func__);
662 return 0;
663}
664
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800665int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700666 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800667{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700668 int i, num_devices = 0;
669 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800670 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 if (snd_device < SND_DEVICE_MIN ||
672 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800673 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800674 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700676
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700677 platform_send_audio_calibration(adev->platform, snd_device);
678
vivek mehtade4849c2016-03-03 17:23:38 -0800679 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700680 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700681 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800682 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 }
684
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700685 /* due to the possibility of calibration overwrite between listen
686 and audio, notify sound trigger hal before audio calibration is sent */
687 audio_extn_sound_trigger_update_device_status(snd_device,
688 ST_EVENT_SND_DEVICE_BUSY);
689
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 if (audio_extn_spkr_prot_is_enabled())
691 audio_extn_spkr_prot_calib_cancel(adev);
692
zhaoyang yin4211fad2015-06-04 21:13:25 +0800693 audio_extn_dsm_feedback_enable(adev, snd_device, true);
694
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700695 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800696 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800697 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
699 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700700 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
703 if (audio_extn_spkr_prot_start_processing(snd_device)) {
704 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800705 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700706 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700707 } else if (platform_can_split_snd_device(snd_device,
708 &num_devices,
709 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700710 for (i = 0; i < num_devices; i++) {
711 enable_snd_device(adev, new_snd_devices[i]);
712 }
vivek mehtab6506412015-08-07 16:55:17 -0700713 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700714 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800715 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
716 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
717 ALOGE(" %s: Invalid sound device returned", __func__);
718 goto on_error;
719 }
Ed Tam70b5c142016-03-21 19:14:29 -0700720
Eric Laurent2e140aa2016-06-30 17:14:46 -0700721 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700722
723 if (is_a2dp_device(snd_device) &&
724 (audio_extn_a2dp_start_playback() < 0)) {
725 ALOGE("%s: failed to configure A2DP control path", __func__);
726 goto on_error;
727 }
728
vivek mehtade4849c2016-03-03 17:23:38 -0800729 audio_route_apply_and_update_path(adev->audio_route, device_name);
730 }
731on_success:
732 adev->snd_dev_ref_cnt[snd_device]++;
733 ret_val = 0;
734on_error:
735 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736}
737
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800738int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700739 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700741 int i, num_devices = 0;
742 snd_device_t new_snd_devices[2];
743
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800744 if (snd_device < SND_DEVICE_MIN ||
745 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800746 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800747 return -EINVAL;
748 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
750 ALOGE("%s: device ref cnt is already 0", __func__);
751 return -EINVAL;
752 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800753 audio_extn_tfa_98xx_disable_speaker(snd_device);
754
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755 adev->snd_dev_ref_cnt[snd_device]--;
756 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800757 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800758
759 if (is_a2dp_device(snd_device))
760 audio_extn_a2dp_stop_playback();
761
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700762 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800763 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700764 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700765 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
766 audio_extn_spkr_prot_is_enabled()) {
767 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700768
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700769 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
770 // and does not use speaker swap. As this code causes a problem with device enable ref
771 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700772 // when speaker device is disabled, reset swap.
773 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700774 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700775
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700776 } else if (platform_can_split_snd_device(snd_device,
777 &num_devices,
778 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700779 for (i = 0; i < num_devices; i++) {
780 disable_snd_device(adev, new_snd_devices[i]);
781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700783 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800784 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
785 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
786 ALOGE(" %s: Invalid sound device returned", __func__);
787 return -EINVAL;
788 }
789
Eric Laurent2e140aa2016-06-30 17:14:46 -0700790 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800791 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700792 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700793 audio_extn_sound_trigger_update_device_status(snd_device,
794 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700795 }
vivek mehtab6506412015-08-07 16:55:17 -0700796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797 return 0;
798}
799
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700800/*
801 legend:
802 uc - existing usecase
803 new_uc - new usecase
804 d1, d11, d2 - SND_DEVICE enums
805 a1, a2 - corresponding ANDROID device enums
806 B, B1, B2 - backend strings
807
808case 1
809 uc->dev d1 (a1) B1
810 new_uc->dev d1 (a1), d2 (a2) B1, B2
811
812 resolution: disable and enable uc->dev on d1
813
814case 2
815 uc->dev d1 (a1) B1
816 new_uc->dev d11 (a1) B1
817
818 resolution: need to switch uc since d1 and d11 are related
819 (e.g. speaker and voice-speaker)
820 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
821
822case 3
823 uc->dev d1 (a1) B1
824 new_uc->dev d2 (a2) B2
825
826 resolution: no need to switch uc
827
828case 4
829 uc->dev d1 (a1) B
830 new_uc->dev d2 (a2) B
831
832 resolution: disable enable uc-dev on d2 since backends match
833 we cannot enable two streams on two different devices if they
834 share the same backend. e.g. if offload is on speaker device using
835 QUAD_MI2S backend and a low-latency stream is started on voice-handset
836 using the same backend, offload must also be switched to voice-handset.
837
838case 5
839 uc->dev d1 (a1) B
840 new_uc->dev d1 (a1), d2 (a2) B
841
842 resolution: disable enable uc-dev on d2 since backends match
843 we cannot enable two streams on two different devices if they
844 share the same backend.
845
846case 6
847 uc->dev d1 a1 B1
848 new_uc->dev d2 a1 B2
849
850 resolution: no need to switch
851
852case 7
853
854 uc->dev d1 (a1), d2 (a2) B1, B2
855 new_uc->dev d1 B1
856
857 resolution: no need to switch
858
859*/
860static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
861 struct audio_usecase *new_uc,
862 snd_device_t new_snd_device)
863{
864 audio_devices_t a1 = uc->stream.out->devices;
865 audio_devices_t a2 = new_uc->stream.out->devices;
866
867 snd_device_t d1 = uc->out_snd_device;
868 snd_device_t d2 = new_snd_device;
869
870 // Treat as a special case when a1 and a2 are not disjoint
871 if ((a1 != a2) && (a1 & a2)) {
872 snd_device_t d3[2];
873 int num_devices = 0;
874 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
875 &num_devices,
876 d3);
877 if (ret < 0) {
878 if (ret != -ENOSYS) {
879 ALOGW("%s failed to split snd_device %d",
880 __func__,
881 popcount(a1) > 1 ? d1 : d2);
882 }
883 goto end;
884 }
885
886 // NB: case 7 is hypothetical and isn't a practical usecase yet.
887 // But if it does happen, we need to give priority to d2 if
888 // the combo devices active on the existing usecase share a backend.
889 // This is because we cannot have a usecase active on a combo device
890 // and a new usecase requests one device in this combo pair.
891 if (platform_check_backends_match(d3[0], d3[1])) {
892 return d2; // case 5
893 } else {
894 return d1; // case 1
895 }
896 } else {
897 if (platform_check_backends_match(d1, d2)) {
898 return d2; // case 2, 4
899 } else {
900 return d1; // case 6, 3
901 }
902 }
903
904end:
905 return d2; // return whatever was calculated before.
906}
907
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700908static void check_and_route_playback_usecases(struct audio_device *adev,
909 struct audio_usecase *uc_info,
910 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911{
912 struct listnode *node;
913 struct audio_usecase *usecase;
914 bool switch_device[AUDIO_USECASE_MAX];
915 int i, num_uc_to_switch = 0;
916
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700917 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
918 uc_info,
919 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700920
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800921 /* For a2dp device reconfigure all active sessions
922 * with new AFE encoder format based on a2dp state
923 */
924 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700925 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
926 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800927 audio_extn_a2dp_is_force_device_switch()) {
928 force_routing = true;
929 }
930
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 /*
932 * This function is to make sure that all the usecases that are active on
933 * the hardware codec backend are always routed to any one device that is
934 * handled by the hardware codec.
935 * For example, if low-latency and deep-buffer usecases are currently active
936 * on speaker and out_set_parameters(headset) is received on low-latency
937 * output, then we have to make sure deep-buffer is also switched to headset,
938 * because of the limitation that both the devices cannot be enabled
939 * at the same time as they share the same backend.
940 */
941 /* Disable all the usecases on the shared backend other than the
942 specified usecase */
943 for (i = 0; i < AUDIO_USECASE_MAX; i++)
944 switch_device[i] = false;
945
946 list_for_each(node, &adev->usecase_list) {
947 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700948 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
949 continue;
950
951 if (force_routing ||
952 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700953 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
954 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700955 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
957 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700958 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700959 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700960 switch_device[usecase->id] = true;
961 num_uc_to_switch++;
962 }
963 }
964
965 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700969 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900970 }
971 }
972
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900974 list_for_each(node, &adev->usecase_list) {
975 usecase = node_to_item(node, struct audio_usecase, list);
976 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700977 d_device = derive_playback_snd_device(usecase, uc_info,
978 snd_device);
979 enable_snd_device(adev, d_device);
980 /* Update the out_snd_device before enabling the audio route */
981 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700982 }
983 }
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 /* Re-route all the usecases on the shared backend other than the
986 specified usecase to new snd devices */
987 list_for_each(node, &adev->usecase_list) {
988 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700990 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 }
992 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993 }
994}
995
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996static void check_and_route_capture_usecases(struct audio_device *adev,
997 struct audio_usecase *uc_info,
998 snd_device_t snd_device)
999{
1000 struct listnode *node;
1001 struct audio_usecase *usecase;
1002 bool switch_device[AUDIO_USECASE_MAX];
1003 int i, num_uc_to_switch = 0;
1004
vivek mehta4ed66e62016-04-15 23:33:34 -07001005 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1006
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001007 /*
1008 * This function is to make sure that all the active capture usecases
1009 * are always routed to the same input sound device.
1010 * For example, if audio-record and voice-call usecases are currently
1011 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1012 * is received for voice call then we have to make sure that audio-record
1013 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1014 * because of the limitation that two devices cannot be enabled
1015 * at the same time if they share the same backend.
1016 */
1017 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1018 switch_device[i] = false;
1019
1020 list_for_each(node, &adev->usecase_list) {
1021 usecase = node_to_item(node, struct audio_usecase, list);
1022 if (usecase->type != PCM_PLAYBACK &&
1023 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001024 usecase->in_snd_device != snd_device &&
1025 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001026 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1027 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001028 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001029 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001030 switch_device[usecase->id] = true;
1031 num_uc_to_switch++;
1032 }
1033 }
1034
1035 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 list_for_each(node, &adev->usecase_list) {
1037 usecase = node_to_item(node, struct audio_usecase, list);
1038 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001039 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001040 }
1041 }
1042
1043 list_for_each(node, &adev->usecase_list) {
1044 usecase = node_to_item(node, struct audio_usecase, list);
1045 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001046 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001047 }
1048 }
1049
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001050 /* Re-route all the usecases on the shared backend other than the
1051 specified usecase to new snd devices */
1052 list_for_each(node, &adev->usecase_list) {
1053 usecase = node_to_item(node, struct audio_usecase, list);
1054 /* Update the in_snd_device only before enabling the audio route */
1055 if (switch_device[usecase->id] ) {
1056 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001057 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001058 }
1059 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 }
1061}
1062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001063/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001064static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001066 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001067 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
1069 switch (channels) {
1070 /*
1071 * Do not handle stereo output in Multi-channel cases
1072 * Stereo case is handled in normal playback path
1073 */
1074 case 6:
1075 ALOGV("%s: HDMI supports 5.1", __func__);
1076 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1077 break;
1078 case 8:
1079 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1080 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1081 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1082 break;
1083 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001084 ALOGE("HDMI does not support multi channel playback");
1085 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 break;
1087 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001088 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089}
1090
Andy Hung18859412017-08-09 11:47:21 -07001091static ssize_t read_usb_sup_sample_rates(bool is_playback,
1092 uint32_t *supported_sample_rates,
1093 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1096 supported_sample_rates,
1097 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001098#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001099 for (ssize_t i=0; i<count; i++) {
1100 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1101 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001102 }
1103#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001104 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001105}
1106
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107static int read_usb_sup_channel_masks(bool is_playback,
1108 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001109 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001110{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001112 int channel_count;
1113 uint32_t num_masks = 0;
1114 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1115 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001116 }
Eric Laurent74b55762017-07-09 17:04:53 -07001117 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001118 // start from 2 channels as framework currently doesn't support mono.
1119 // TODO: consider only supporting channel index masks beyond stereo here.
1120 for (channel_count = FCC_2;
1121 channel_count <= channels && num_masks < max_masks;
1122 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001123 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1124 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001125 for (channel_count = FCC_2;
1126 channel_count <= channels && num_masks < max_masks;
1127 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001128 supported_channel_masks[num_masks++] =
1129 audio_channel_mask_for_index_assignment_from_count(channel_count);
1130 }
1131 } else {
1132 // For capture we report all supported channel masks from 1 channel up.
1133 channel_count = MIN_CHANNEL_COUNT;
1134 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1135 // indexed mask
1136 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1137 supported_channel_masks[num_masks++] =
1138 audio_channel_in_mask_from_count(channel_count);
1139 }
1140 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001141#ifdef NDEBUG
1142 for (size_t i = 0; i < num_masks; ++i) {
1143 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1144 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1145 }
1146#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001147 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148}
1149
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001150static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 audio_format_t *supported_formats,
1152 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001153{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001155 switch (bitwidth) {
1156 case 24:
1157 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001158 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001159 break;
1160 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001161 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001162 break;
1163 case 16:
1164 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001165 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001166 break;
1167 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001168 ALOGV("%s: %s supported format %d", __func__,
1169 is_playback ? "P" : "C", bitwidth);
1170 return 1;
1171}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001172
Haynes Mathew George569b7482017-05-08 14:44:27 -07001173static int read_usb_sup_params_and_compare(bool is_playback,
1174 audio_format_t *format,
1175 audio_format_t *supported_formats,
1176 uint32_t max_formats,
1177 audio_channel_mask_t *mask,
1178 audio_channel_mask_t *supported_channel_masks,
1179 uint32_t max_masks,
1180 uint32_t *rate,
1181 uint32_t *supported_sample_rates,
1182 uint32_t max_rates) {
1183 int ret = 0;
1184 int num_formats;
1185 int num_masks;
1186 int num_rates;
1187 int i;
1188
1189 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1190 max_formats);
1191 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1192 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001193
Haynes Mathew George569b7482017-05-08 14:44:27 -07001194 num_rates = read_usb_sup_sample_rates(is_playback,
1195 supported_sample_rates, max_rates);
1196
1197#define LUT(table, len, what, dflt) \
1198 for (i=0; i<len && (table[i] != what); i++); \
1199 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1200
1201 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1202 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1203 LUT(supported_sample_rates, num_rates, *rate, 0);
1204
1205#undef LUT
1206 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001207}
1208
Andy Hungd9653bd2017-08-01 19:31:39 -07001209static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1210{
1211 // Check if usb is ready.
1212 // The usb device may have been removed quickly after insertion and hence
1213 // no longer available. This will show up as empty channel masks, or rates.
1214
1215 pthread_mutex_lock(&adev->lock);
1216 uint32_t supported_sample_rate;
1217
1218 // we consider usb ready if we can fetch at least one sample rate.
1219 const bool ready = read_usb_sup_sample_rates(
1220 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1221 pthread_mutex_unlock(&adev->lock);
1222 return ready;
1223}
1224
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001225static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1226{
1227 struct audio_usecase *usecase;
1228 struct listnode *node;
1229
1230 list_for_each(node, &adev->usecase_list) {
1231 usecase = node_to_item(node, struct audio_usecase, list);
1232 if (usecase->type == VOICE_CALL) {
1233 ALOGV("%s: usecase id %d", __func__, usecase->id);
1234 return usecase->id;
1235 }
1236 }
1237 return USECASE_INVALID;
1238}
1239
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001240struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1241 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001242{
1243 struct audio_usecase *usecase;
1244 struct listnode *node;
1245
1246 list_for_each(node, &adev->usecase_list) {
1247 usecase = node_to_item(node, struct audio_usecase, list);
1248 if (usecase->id == uc_id)
1249 return usecase;
1250 }
1251 return NULL;
1252}
1253
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001254static bool force_device_switch(struct audio_usecase *usecase)
1255{
1256 if (usecase->stream.out == NULL) {
1257 ALOGE("%s: stream.out is NULL", __func__);
1258 return false;
1259 }
1260
1261 // Force all A2DP output devices to reconfigure for proper AFE encode format
1262 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1263 // in suspended state, hence try to trigger a retry when we again get a routing request.
1264 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1265 audio_extn_a2dp_is_force_device_switch()) {
1266 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1267 return true;
1268 }
1269
1270 return false;
1271}
1272
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001273int select_devices(struct audio_device *adev,
1274 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001276 snd_device_t out_snd_device = SND_DEVICE_NONE;
1277 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278 struct audio_usecase *usecase = NULL;
1279 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001280 struct audio_usecase *hfp_usecase = NULL;
1281 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001282 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001283 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001284 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1285 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 usecase = get_usecase_from_list(adev, uc_id);
1288 if (usecase == NULL) {
1289 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1290 return -EINVAL;
1291 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001293 if ((usecase->type == VOICE_CALL) ||
1294 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001295 out_snd_device = platform_get_output_snd_device(adev->platform,
1296 usecase->stream.out->devices);
1297 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 usecase->devices = usecase->stream.out->devices;
1299 } else {
1300 /*
1301 * If the voice call is active, use the sound devices of voice call usecase
1302 * so that it would not result any device switch. All the usecases will
1303 * be switched to new device when select_devices() is called for voice call
1304 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001305 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001306 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001307 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001308 vc_usecase = get_usecase_from_list(adev,
1309 get_voice_usecase_id_from_list(adev));
1310 if ((vc_usecase != NULL) &&
1311 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1312 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 in_snd_device = vc_usecase->in_snd_device;
1314 out_snd_device = vc_usecase->out_snd_device;
1315 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001316 } else if (audio_extn_hfp_is_active(adev)) {
1317 hfp_ucid = audio_extn_hfp_get_usecase();
1318 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1319 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1320 in_snd_device = hfp_usecase->in_snd_device;
1321 out_snd_device = hfp_usecase->out_snd_device;
1322 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001323 }
1324 if (usecase->type == PCM_PLAYBACK) {
1325 usecase->devices = usecase->stream.out->devices;
1326 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001327 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001328 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001329
Eric Laurentb23d5282013-05-14 15:27:20 -07001330 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001331 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001332
1333 if (voip_usecase)
1334 voip_out = voip_usecase->stream.out;
1335
1336 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001337 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001338 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001339 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001340 select_devices(adev, adev->active_input->usecase);
1341 }
1342 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001343 } else if (usecase->type == PCM_CAPTURE) {
1344 usecase->devices = usecase->stream.in->device;
1345 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001346 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001347 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001348 if (adev->active_input &&
1349 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1350 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001351
1352 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1353 USECASE_AUDIO_PLAYBACK_VOIP);
1354
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001355 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001356 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1357 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001358 } else if (voip_usecase) {
1359 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001360 } else if (adev->primary_output) {
1361 out_device = adev->primary_output->devices;
1362 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001363 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001364 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001365 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 }
1367 }
1368
1369 if (out_snd_device == usecase->out_snd_device &&
1370 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001371 if (!force_device_switch(usecase))
1372 return 0;
1373 }
1374
1375 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1376 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1377 return 0;
1378 }
1379
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001380 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1381 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001382 (!audio_extn_a2dp_is_ready())) {
1383 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001384 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1385 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1386 else
1387 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 }
1389
juyuchen66c4ecf2018-08-06 15:39:34 +08001390 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1391 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1392 }
1393
Eric Laurent2bafff12016-03-17 12:17:23 -07001394 if (out_snd_device != SND_DEVICE_NONE &&
1395 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1396 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1397 __func__,
1398 use_case_table[uc_id],
1399 adev->last_logged_snd_device[uc_id][0],
1400 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1401 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1402 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1403 -1,
1404 out_snd_device,
1405 platform_get_snd_device_name(out_snd_device),
1406 platform_get_snd_device_acdb_id(out_snd_device));
1407 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1408 }
1409 if (in_snd_device != SND_DEVICE_NONE &&
1410 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1411 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1412 __func__,
1413 use_case_table[uc_id],
1414 adev->last_logged_snd_device[uc_id][1],
1415 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1416 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1417 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1418 -1,
1419 in_snd_device,
1420 platform_get_snd_device_name(in_snd_device),
1421 platform_get_snd_device_acdb_id(in_snd_device));
1422 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1423 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001424
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 /*
1426 * Limitation: While in call, to do a device switch we need to disable
1427 * and enable both RX and TX devices though one of them is same as current
1428 * device.
1429 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001430 if ((usecase->type == VOICE_CALL) &&
1431 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1432 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001433 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001434 /* Disable sidetone only if voice call already exists */
1435 if (voice_is_call_state_active(adev))
1436 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001437 }
1438
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001439 /* Disable current sound devices */
1440 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001441 disable_audio_route(adev, usecase);
1442 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 }
1444
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001445 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001446 disable_audio_route(adev, usecase);
1447 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001448 }
1449
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001450 /* Applicable only on the targets that has external modem.
1451 * New device information should be sent to modem before enabling
1452 * the devices to reduce in-call device switch time.
1453 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001454 if ((usecase->type == VOICE_CALL) &&
1455 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1456 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001457 status = platform_switch_voice_call_enable_device_config(adev->platform,
1458 out_snd_device,
1459 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001460 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 /* Enable new sound devices */
1463 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001464 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001465 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1466 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001467 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001468 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469 }
1470
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001471 if (in_snd_device != SND_DEVICE_NONE) {
1472 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001473 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001474 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
Eric Laurentb23d5282013-05-14 15:27:20 -07001476 if (usecase->type == VOICE_CALL)
1477 status = platform_switch_voice_call_device_post(adev->platform,
1478 out_snd_device,
1479 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001480
sangwoo170731f2013-06-08 15:36:36 +09001481 usecase->in_snd_device = in_snd_device;
1482 usecase->out_snd_device = out_snd_device;
1483
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001484 audio_extn_tfa_98xx_set_mode();
1485
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001486 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001487
Jasmine Cha70771b62018-05-15 15:02:43 +08001488 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001489
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001490 /* Applicable only on the targets that has external modem.
1491 * Enable device command should be sent to modem only after
1492 * enabling voice call mixer controls
1493 */
vivek mehta765eb642015-08-07 19:46:06 -07001494 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001495 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1496 out_snd_device,
1497 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001498 /* Enable sidetone only if voice call already exists */
1499 if (voice_is_call_state_active(adev))
1500 voice_set_sidetone(adev, out_snd_device, true);
1501 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001502
Yung Ti Su0bb200f2018-06-22 17:38:47 +08001503 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001504 struct stream_out *voip_out = voip_usecase->stream.out;
1505 audio_extn_utils_send_app_type_gain(adev,
1506 voip_out->app_type_cfg.app_type,
1507 &voip_out->app_type_cfg.gain[0]);
1508 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509 return status;
1510}
1511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512static int stop_input_stream(struct stream_in *in)
1513{
1514 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515 struct audio_usecase *uc_info;
1516 struct audio_device *adev = in->dev;
1517
Eric Laurent994a6932013-07-17 11:51:42 -07001518 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001520
1521 if (adev->active_input) {
1522 if (adev->active_input->usecase == in->usecase) {
1523 adev->active_input = NULL;
1524 } else {
1525 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1526 __func__,
1527 use_case_table[adev->active_input->usecase],
1528 use_case_table[in->usecase]);
1529 }
1530 }
1531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 uc_info = get_usecase_from_list(adev, in->usecase);
1533 if (uc_info == NULL) {
1534 ALOGE("%s: Could not find the usecase (%d) in the list",
1535 __func__, in->usecase);
1536 return -EINVAL;
1537 }
1538
vivek mehta781065c2017-04-04 12:55:01 -07001539 /* Close in-call recording streams */
1540 voice_check_and_stop_incall_rec_usecase(adev, in);
1541
Eric Laurent150dbfe2013-02-27 14:31:02 -08001542 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001543 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544
1545 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001546 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001548 list_remove(&uc_info->list);
1549 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001550
Eric Laurent994a6932013-07-17 11:51:42 -07001551 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 return ret;
1553}
1554
1555int start_input_stream(struct stream_in *in)
1556{
1557 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001558 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 struct audio_usecase *uc_info;
1560 struct audio_device *adev = in->dev;
1561
Eric Laurent994a6932013-07-17 11:51:42 -07001562 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001563
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001564 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1565 return -EIO;
1566
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001567 if (in->card_status == CARD_STATUS_OFFLINE ||
1568 adev->card_status == CARD_STATUS_OFFLINE) {
1569 ALOGW("in->card_status or adev->card_status offline, try again");
1570 ret = -EAGAIN;
1571 goto error_config;
1572 }
1573
vivek mehta781065c2017-04-04 12:55:01 -07001574 /* Check if source matches incall recording usecase criteria */
1575 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1576 if (ret)
1577 goto error_config;
1578 else
1579 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1580
Eric Laurentb23d5282013-05-14 15:27:20 -07001581 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001582 if (in->pcm_device_id < 0) {
1583 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1584 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001585 ret = -EINVAL;
1586 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001588
1589 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1591 uc_info->id = in->usecase;
1592 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001593 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 uc_info->devices = in->device;
1595 uc_info->in_snd_device = SND_DEVICE_NONE;
1596 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001598 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001599
Wei Wangf4837d52017-11-21 14:51:20 -08001600 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001601 audio_extn_perf_lock_acquire();
1602
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604
Eric Laurent0e46adf2016-12-16 12:49:24 -08001605 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001606 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001607 ALOGE("%s: pcm stream not ready", __func__);
1608 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001609 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001610 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001611 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001612 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1613 goto error_open;
1614 }
1615 } else {
1616 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1617 unsigned int pcm_open_retry_count = 0;
1618
1619 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1620 flags |= PCM_MMAP | PCM_NOIRQ;
1621 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1622 } else if (in->realtime) {
1623 flags |= PCM_MMAP | PCM_NOIRQ;
1624 }
1625
1626 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1627 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1628
1629 while (1) {
1630 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1631 flags, &in->config);
1632 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1633 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1634 if (in->pcm != NULL) {
1635 pcm_close(in->pcm);
1636 in->pcm = NULL;
1637 }
1638 if (pcm_open_retry_count-- == 0) {
1639 ret = -EIO;
1640 goto error_open;
1641 }
1642 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1643 continue;
1644 }
1645 break;
1646 }
1647
1648 ALOGV("%s: pcm_prepare", __func__);
1649 ret = pcm_prepare(in->pcm);
1650 if (ret < 0) {
1651 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001652 pcm_close(in->pcm);
1653 in->pcm = NULL;
1654 goto error_open;
1655 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001656 if (in->realtime) {
1657 ret = pcm_start(in->pcm);
1658 if (ret < 0) {
1659 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1660 pcm_close(in->pcm);
1661 in->pcm = NULL;
1662 goto error_open;
1663 }
1664 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001665 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001666 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001667 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001668 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001669 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001670
Eric Laurent0e46adf2016-12-16 12:49:24 -08001671 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001672
1673error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001675 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001676 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001677
1678error_config:
1679 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001680 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001681 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682}
1683
Eric Laurenta1478072015-09-21 17:21:52 -07001684void lock_input_stream(struct stream_in *in)
1685{
1686 pthread_mutex_lock(&in->pre_lock);
1687 pthread_mutex_lock(&in->lock);
1688 pthread_mutex_unlock(&in->pre_lock);
1689}
1690
1691void lock_output_stream(struct stream_out *out)
1692{
1693 pthread_mutex_lock(&out->pre_lock);
1694 pthread_mutex_lock(&out->lock);
1695 pthread_mutex_unlock(&out->pre_lock);
1696}
1697
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001698/* must be called with out->lock locked */
1699static int send_offload_cmd_l(struct stream_out* out, int command)
1700{
1701 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1702
1703 ALOGVV("%s %d", __func__, command);
1704
1705 cmd->cmd = command;
1706 list_add_tail(&out->offload_cmd_list, &cmd->node);
1707 pthread_cond_signal(&out->offload_cond);
1708 return 0;
1709}
1710
1711/* must be called iwth out->lock locked */
1712static void stop_compressed_output_l(struct stream_out *out)
1713{
1714 out->offload_state = OFFLOAD_STATE_IDLE;
1715 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001716 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717 if (out->compr != NULL) {
1718 compress_stop(out->compr);
1719 while (out->offload_thread_blocked) {
1720 pthread_cond_wait(&out->cond, &out->lock);
1721 }
1722 }
1723}
1724
1725static void *offload_thread_loop(void *context)
1726{
1727 struct stream_out *out = (struct stream_out *) context;
1728 struct listnode *item;
1729
1730 out->offload_state = OFFLOAD_STATE_IDLE;
1731 out->playback_started = 0;
1732
1733 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1734 set_sched_policy(0, SP_FOREGROUND);
1735 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1736
1737 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001738 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001739 for (;;) {
1740 struct offload_cmd *cmd = NULL;
1741 stream_callback_event_t event;
1742 bool send_callback = false;
1743
1744 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1745 __func__, list_empty(&out->offload_cmd_list),
1746 out->offload_state);
1747 if (list_empty(&out->offload_cmd_list)) {
1748 ALOGV("%s SLEEPING", __func__);
1749 pthread_cond_wait(&out->offload_cond, &out->lock);
1750 ALOGV("%s RUNNING", __func__);
1751 continue;
1752 }
1753
1754 item = list_head(&out->offload_cmd_list);
1755 cmd = node_to_item(item, struct offload_cmd, node);
1756 list_remove(item);
1757
1758 ALOGVV("%s STATE %d CMD %d out->compr %p",
1759 __func__, out->offload_state, cmd->cmd, out->compr);
1760
1761 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1762 free(cmd);
1763 break;
1764 }
1765
1766 if (out->compr == NULL) {
1767 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001768 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001769 pthread_cond_signal(&out->cond);
1770 continue;
1771 }
1772 out->offload_thread_blocked = true;
1773 pthread_mutex_unlock(&out->lock);
1774 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001775 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1777 compress_wait(out->compr, -1);
1778 send_callback = true;
1779 event = STREAM_CBK_EVENT_WRITE_READY;
1780 break;
1781 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782 compress_next_track(out->compr);
1783 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 send_callback = true;
1785 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001786 /* Resend the metadata for next iteration */
1787 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788 break;
1789 case OFFLOAD_CMD_DRAIN:
1790 compress_drain(out->compr);
1791 send_callback = true;
1792 event = STREAM_CBK_EVENT_DRAIN_READY;
1793 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001794 case OFFLOAD_CMD_ERROR:
1795 send_callback = true;
1796 event = STREAM_CBK_EVENT_ERROR;
1797 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 default:
1799 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1800 break;
1801 }
Eric Laurenta1478072015-09-21 17:21:52 -07001802 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 out->offload_thread_blocked = false;
1804 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001805 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001806 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001808 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001809 free(cmd);
1810 }
1811
1812 pthread_cond_signal(&out->cond);
1813 while (!list_empty(&out->offload_cmd_list)) {
1814 item = list_head(&out->offload_cmd_list);
1815 list_remove(item);
1816 free(node_to_item(item, struct offload_cmd, node));
1817 }
1818 pthread_mutex_unlock(&out->lock);
1819
1820 return NULL;
1821}
1822
1823static int create_offload_callback_thread(struct stream_out *out)
1824{
1825 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1826 list_init(&out->offload_cmd_list);
1827 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1828 offload_thread_loop, out);
1829 return 0;
1830}
1831
1832static int destroy_offload_callback_thread(struct stream_out *out)
1833{
Eric Laurenta1478072015-09-21 17:21:52 -07001834 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001835 stop_compressed_output_l(out);
1836 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1837
1838 pthread_mutex_unlock(&out->lock);
1839 pthread_join(out->offload_thread, (void **) NULL);
1840 pthread_cond_destroy(&out->offload_cond);
1841
1842 return 0;
1843}
1844
Eric Laurent07eeafd2013-10-06 12:52:49 -07001845static bool allow_hdmi_channel_config(struct audio_device *adev)
1846{
1847 struct listnode *node;
1848 struct audio_usecase *usecase;
1849 bool ret = true;
1850
1851 list_for_each(node, &adev->usecase_list) {
1852 usecase = node_to_item(node, struct audio_usecase, list);
1853 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1854 /*
1855 * If voice call is already existing, do not proceed further to avoid
1856 * disabling/enabling both RX and TX devices, CSD calls, etc.
1857 * Once the voice call done, the HDMI channels can be configured to
1858 * max channels of remaining use cases.
1859 */
1860 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001861 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001862 __func__);
1863 ret = false;
1864 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001865 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1866 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001867 "no change in HDMI channels", __func__);
1868 ret = false;
1869 break;
1870 }
1871 }
1872 }
1873 return ret;
1874}
1875
1876static int check_and_set_hdmi_channels(struct audio_device *adev,
1877 unsigned int channels)
1878{
1879 struct listnode *node;
1880 struct audio_usecase *usecase;
1881
1882 /* Check if change in HDMI channel config is allowed */
1883 if (!allow_hdmi_channel_config(adev))
1884 return 0;
1885
1886 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001887 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001888 return 0;
1889 }
1890
1891 platform_set_hdmi_channels(adev->platform, channels);
1892 adev->cur_hdmi_channels = channels;
1893
1894 /*
1895 * Deroute all the playback streams routed to HDMI so that
1896 * the back end is deactivated. Note that backend will not
1897 * be deactivated if any one stream is connected to it.
1898 */
1899 list_for_each(node, &adev->usecase_list) {
1900 usecase = node_to_item(node, struct audio_usecase, list);
1901 if (usecase->type == PCM_PLAYBACK &&
1902 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001903 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001904 }
1905 }
1906
1907 /*
1908 * Enable all the streams disabled above. Now the HDMI backend
1909 * will be activated with new channel configuration
1910 */
1911 list_for_each(node, &adev->usecase_list) {
1912 usecase = node_to_item(node, struct audio_usecase, list);
1913 if (usecase->type == PCM_PLAYBACK &&
1914 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001915 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001916 }
1917 }
1918
1919 return 0;
1920}
1921
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001922static int check_and_set_usb_service_interval(struct audio_device *adev,
1923 struct audio_usecase *uc_info,
1924 bool min)
1925{
1926 struct listnode *node;
1927 struct audio_usecase *usecase;
1928 bool switch_usecases = false;
1929 bool reconfig = false;
1930
1931 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1932 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1933 return -1;
1934
1935 /* set if the valid usecase do not already exist */
1936 list_for_each(node, &adev->usecase_list) {
1937 usecase = node_to_item(node, struct audio_usecase, list);
1938 if (usecase->type == PCM_PLAYBACK &&
1939 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1940 switch (usecase->id) {
1941 case USECASE_AUDIO_PLAYBACK_MMAP:
1942 case USECASE_AUDIO_PLAYBACK_ULL:
1943 // cannot reconfig while mmap/ull is present.
1944 return -1;
1945 default:
1946 switch_usecases = true;
1947 break;
1948 }
1949 }
1950 if (switch_usecases)
1951 break;
1952 }
1953 /*
1954 * client can try to set service interval in start_output_stream
1955 * to min or to 0 (i.e reset) in stop_output_stream .
1956 */
1957 unsigned long service_interval =
1958 audio_extn_usb_find_service_interval(min, true /*playback*/);
1959 int ret = platform_set_usb_service_interval(adev->platform,
1960 true /*playback*/,
1961 service_interval,
1962 &reconfig);
1963 /* no change or not supported or no active usecases */
1964 if (ret || !reconfig || !switch_usecases)
1965 return -1;
1966 return 0;
1967#undef VALID_USECASE
1968}
1969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970static int stop_output_stream(struct stream_out *out)
1971{
1972 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973 struct audio_usecase *uc_info;
1974 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001975 bool has_voip_usecase =
1976 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977
Eric Laurent994a6932013-07-17 11:51:42 -07001978 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001979 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 uc_info = get_usecase_from_list(adev, out->usecase);
1981 if (uc_info == NULL) {
1982 ALOGE("%s: Could not find the usecase (%d) in the list",
1983 __func__, out->usecase);
1984 return -EINVAL;
1985 }
1986
Haynes Mathew George41f86652014-06-17 14:22:15 -07001987 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1988 if (adev->visualizer_stop_output != NULL)
1989 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1990 if (adev->offload_effects_stop_output != NULL)
1991 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001992 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1993 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1994 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001995 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001996
Eric Laurent150dbfe2013-02-27 14:31:02 -08001997 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001998 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001999
2000 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002001 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002003 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004
Eric Laurent0499d4f2014-08-25 22:39:29 -05002005 audio_extn_extspk_update(adev->extspk);
2006
Eric Laurent07eeafd2013-10-06 12:52:49 -07002007 /* Must be called after removing the usecase from list */
2008 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2009 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002010 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002011 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2012 if (ret == 0) {
2013 /* default service interval was successfully updated,
2014 reopen USB backend with new service interval */
2015 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2016 }
2017 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002018 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002019
HW Lee88512e92018-06-12 15:26:09 +08002020 if (has_voip_usecase ||
2021 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2022 struct listnode *node;
2023 struct audio_usecase *usecase;
2024 list_for_each(node, &adev->usecase_list) {
2025 usecase = node_to_item(node, struct audio_usecase, list);
2026 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2027 continue;
2028
2029 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2030 __func__, usecase->id, use_case_table[usecase->id],
2031 out->usecase, use_case_table[out->usecase]);
2032 select_devices(adev, usecase->id);
2033 }
2034 }
2035
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002036 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002037 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038 return ret;
2039}
2040
2041int start_output_stream(struct stream_out *out)
2042{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 struct audio_usecase *uc_info;
2045 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002046 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047
Eric Laurent994a6932013-07-17 11:51:42 -07002048 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002049 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002050
2051 if (out->card_status == CARD_STATUS_OFFLINE ||
2052 adev->card_status == CARD_STATUS_OFFLINE) {
2053 ALOGW("out->card_status or adev->card_status offline, try again");
2054 ret = -EAGAIN;
2055 goto error_config;
2056 }
2057
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002058 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2059 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002060 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002061 a2dp_combo = true;
2062 } else {
2063 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2064 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2065 ret = -EAGAIN;
2066 goto error_config;
2067 }
2068 }
2069 }
2070 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002071 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 if (out->pcm_device_id < 0) {
2073 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2074 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002075 ret = -EINVAL;
2076 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 }
2078
2079 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2080 uc_info->id = out->usecase;
2081 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002082 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002083 uc_info->devices = out->devices;
2084 uc_info->in_snd_device = SND_DEVICE_NONE;
2085 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Eric Laurent07eeafd2013-10-06 12:52:49 -07002087 /* This must be called before adding this usecase to the list */
2088 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2089 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002090 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2091 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2092 /* USB backend is not reopened immediately.
2093 This is eventually done as part of select_devices */
2094 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002095
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002096 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097
Wei Wangf4837d52017-11-21 14:51:20 -08002098 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002099 audio_extn_perf_lock_acquire();
2100
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002101 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2102 (!audio_extn_a2dp_is_ready())) {
2103 if (!a2dp_combo) {
2104 check_a2dp_restore_l(adev, out, false);
2105 } else {
2106 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002107 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2108 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2109 else
2110 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002111 select_devices(adev, out->usecase);
2112 out->devices = dev;
2113 }
2114 } else {
2115 select_devices(adev, out->usecase);
2116 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002117
Eric Laurent0499d4f2014-08-25 22:39:29 -05002118 audio_extn_extspk_update(adev->extspk);
2119
Andy Hung31aca912014-03-20 17:14:59 -07002120 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002121 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002122 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2123 out->pcm = NULL;
2124 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2125 COMPRESS_IN, &out->compr_config);
2126 if (out->compr && !is_compress_ready(out->compr)) {
2127 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2128 compress_close(out->compr);
2129 out->compr = NULL;
2130 ret = -EIO;
2131 goto error_open;
2132 }
2133 if (out->offload_callback)
2134 compress_nonblock(out->compr, out->non_blocking);
2135
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07002136 if (adev->visualizer_start_output != NULL) {
2137 int capture_device_id =
2138 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2139 PCM_CAPTURE);
2140 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2141 adev->snd_card, capture_device_id);
2142 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002143 if (adev->offload_effects_start_output != NULL)
2144 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2145 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002147 ALOGE("%s: pcm stream not ready", __func__);
2148 goto error_open;
2149 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002150 ret = pcm_start(out->pcm);
2151 if (ret < 0) {
2152 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2153 goto error_open;
2154 }
2155 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002156 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002157 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002158
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002159 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2160 flags |= PCM_MMAP | PCM_NOIRQ;
2161 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002162 } else if (out->realtime) {
2163 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002164 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002165
2166 while (1) {
2167 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2168 flags, &out->config);
2169 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2170 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2171 if (out->pcm != NULL) {
2172 pcm_close(out->pcm);
2173 out->pcm = NULL;
2174 }
2175 if (pcm_open_retry_count-- == 0) {
2176 ret = -EIO;
2177 goto error_open;
2178 }
2179 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2180 continue;
2181 }
2182 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002184 ALOGV("%s: pcm_prepare", __func__);
2185 if (pcm_is_ready(out->pcm)) {
2186 ret = pcm_prepare(out->pcm);
2187 if (ret < 0) {
2188 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2189 pcm_close(out->pcm);
2190 out->pcm = NULL;
2191 goto error_open;
2192 }
2193 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002194 if (out->realtime) {
2195 ret = pcm_start(out->pcm);
2196 if (ret < 0) {
2197 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2198 pcm_close(out->pcm);
2199 out->pcm = NULL;
2200 goto error_open;
2201 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002202 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002203 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002204 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002205 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002206 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002207 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002208
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002209 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2210 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2211 audio_low_latency_hint_start();
2212 }
2213
vivek mehtae59cfb22017-06-16 15:57:11 -07002214 // consider a scenario where on pause lower layers are tear down.
2215 // so on resume, swap mixer control need to be sent only when
2216 // backend is active, hence rather than sending from enable device
2217 // sending it from start of streamtream
2218
2219 platform_set_swap_channels(adev, true);
2220
Eric Laurent994a6932013-07-17 11:51:42 -07002221 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002222 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002223error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002224 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002225 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002227error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002228 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229}
2230
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231static int check_input_parameters(uint32_t sample_rate,
2232 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002233 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002235 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2236 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002237 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2238 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002239 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2240 return -EINVAL;
2241 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
Eric Laurent74b55762017-07-09 17:04:53 -07002243 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2244 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002245 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002246 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002247 return -EINVAL;
2248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
2250 switch (sample_rate) {
2251 case 8000:
2252 case 11025:
2253 case 12000:
2254 case 16000:
2255 case 22050:
2256 case 24000:
2257 case 32000:
2258 case 44100:
2259 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002260 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 break;
2262 default:
vivek mehtadae44712015-07-27 14:13:18 -07002263 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264 return -EINVAL;
2265 }
2266
2267 return 0;
2268}
2269
Kevin Rocarda325aa22018-04-03 09:15:52 -07002270/** Add a value in a list if not already present.
2271 * @return true if value was successfully inserted or already present,
2272 * false if the list is full and does not contain the value.
2273 */
2274static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2275 for (size_t i = 0; i < list_length; i++) {
2276 if (list[i] == value) return true; // value is already present
2277 if (list[i] == 0) { // no values in this slot
2278 list[i] = value;
2279 return true; // value inserted
2280 }
2281 }
2282 return false; // could not insert value
2283}
2284
2285/** Add channel_mask in supported_channel_masks if not already present.
2286 * @return true if channel_mask was successfully inserted or already present,
2287 * false if supported_channel_masks is full and does not contain channel_mask.
2288 */
2289static void register_channel_mask(audio_channel_mask_t channel_mask,
2290 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2291 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2292 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2293}
2294
2295/** Add format in supported_formats if not already present.
2296 * @return true if format was successfully inserted or already present,
2297 * false if supported_formats is full and does not contain format.
2298 */
2299static void register_format(audio_format_t format,
2300 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2301 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2302 "%s: stream can not declare supporting its format %x", __func__, format);
2303}
2304/** Add sample_rate in supported_sample_rates if not already present.
2305 * @return true if sample_rate was successfully inserted or already present,
2306 * false if supported_sample_rates is full and does not contain sample_rate.
2307 */
2308static void register_sample_rate(uint32_t sample_rate,
2309 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2310 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2311 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2312}
2313
vivek mehtaa68fea62017-06-08 19:04:02 -07002314static size_t get_stream_buffer_size(size_t duration_ms,
2315 uint32_t sample_rate,
2316 audio_format_t format,
2317 int channel_count,
2318 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319{
2320 size_t size = 0;
2321
vivek mehtaa68fea62017-06-08 19:04:02 -07002322 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002323 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002324 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002325
2326 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327
Glenn Kasten4f993392014-05-14 07:30:48 -07002328 /* make sure the size is multiple of 32 bytes
2329 * At 48 kHz mono 16-bit PCM:
2330 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2331 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2332 */
2333 size += 0x1f;
2334 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002335
2336 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337}
2338
2339static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344}
2345
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002346static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347{
2348 return -ENOSYS;
2349}
2350
2351static size_t out_get_buffer_size(const struct audio_stream *stream)
2352{
2353 struct stream_out *out = (struct stream_out *)stream;
2354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2356 return out->compr_config.fragment_size;
2357 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002358 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002359 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360}
2361
2362static uint32_t out_get_channels(const struct audio_stream *stream)
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365
2366 return out->channel_mask;
2367}
2368
2369static audio_format_t out_get_format(const struct audio_stream *stream)
2370{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 struct stream_out *out = (struct stream_out *)stream;
2372
2373 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374}
2375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002376static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377{
2378 return -ENOSYS;
2379}
2380
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002381/* must be called with out->lock locked */
2382static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383{
2384 struct stream_out *out = (struct stream_out *)stream;
2385 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002386 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002389 if (adev->adm_deregister_stream)
2390 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002391 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2394 if (out->pcm) {
2395 pcm_close(out->pcm);
2396 out->pcm = NULL;
2397 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002398 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002399 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002400 out->playback_started = false;
2401 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402 } else {
2403 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002404 out->gapless_mdata.encoder_delay = 0;
2405 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 if (out->compr != NULL) {
2407 compress_close(out->compr);
2408 out->compr = NULL;
2409 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002410 }
Phil Burkbc991042017-02-24 08:06:44 -08002411 if (do_stop) {
2412 stop_output_stream(out);
2413 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002414 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002416 return 0;
2417}
2418
2419static int out_standby(struct audio_stream *stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422
2423 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2424 out->usecase, use_case_table[out->usecase]);
2425
2426 lock_output_stream(out);
2427 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002429 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 return 0;
2431}
2432
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002433static int out_on_error(struct audio_stream *stream)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 struct audio_device *adev = out->dev;
2437 bool do_standby = false;
2438
2439 lock_output_stream(out);
2440 if (!out->standby) {
2441 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2442 stop_compressed_output_l(out);
2443 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2444 } else
2445 do_standby = true;
2446 }
2447 pthread_mutex_unlock(&out->lock);
2448
2449 if (do_standby)
2450 return out_standby(&out->stream.common);
2451
2452 return 0;
2453}
2454
Andy Hung7401c7c2016-09-21 12:41:21 -07002455static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456{
Andy Hung7401c7c2016-09-21 12:41:21 -07002457 struct stream_out *out = (struct stream_out *)stream;
2458
2459 // We try to get the lock for consistency,
2460 // but it isn't necessary for these variables.
2461 // If we're not in standby, we may be blocked on a write.
2462 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2463 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2464 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2465
2466 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002467 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002468 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002469
2470 // dump error info
2471 (void)error_log_dump(
2472 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 return 0;
2475}
2476
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002477static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2478{
2479 int ret = 0;
2480 char value[32];
2481 struct compr_gapless_mdata tmp_mdata;
2482
2483 if (!out || !parms) {
2484 return -EINVAL;
2485 }
2486
2487 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2488 if (ret >= 0) {
2489 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2490 } else {
2491 return -EINVAL;
2492 }
2493
2494 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2495 if (ret >= 0) {
2496 tmp_mdata.encoder_padding = atoi(value);
2497 } else {
2498 return -EINVAL;
2499 }
2500
2501 out->gapless_mdata = tmp_mdata;
2502 out->send_new_metadata = 1;
2503 ALOGV("%s new encoder delay %u and padding %u", __func__,
2504 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2505
2506 return 0;
2507}
2508
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002509static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2510{
2511 return out == adev->primary_output || out == adev->voice_tx_output;
2512}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002513
Kevin Rocard1e02c882017-08-09 15:26:07 -07002514static int get_alive_usb_card(struct str_parms* parms) {
2515 int card;
2516 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2517 !audio_extn_usb_alive(card)) {
2518 return card;
2519 }
2520 return -ENODEV;
2521}
2522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002527 struct audio_usecase *usecase;
2528 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 struct str_parms *parms;
2530 char value[32];
2531 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002532 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002533 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002534 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535
Eric Laurent2e140aa2016-06-30 17:14:46 -07002536 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 parms = str_parms_create_str(kvpairs);
2539 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2540 if (ret >= 0) {
2541 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002542
Eric Laurenta1478072015-09-21 17:21:52 -07002543 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002544
2545 // The usb driver needs to be closed after usb device disconnection
2546 // otherwise audio is no longer played on the new usb devices.
2547 // By forcing the stream in standby, the usb stack refcount drops to 0
2548 // and the driver is closed.
2549 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2550 audio_is_usb_out_device(out->devices)) {
2551 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2552 out_standby_l(&out->stream.common);
2553 }
2554
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002557 /*
2558 * When HDMI cable is unplugged the music playback is paused and
2559 * the policy manager sends routing=0. But the audioflinger
2560 * continues to write data until standby time (3sec).
2561 * As the HDMI core is turned off, the write gets blocked.
2562 * Avoid this by routing audio to speaker until standby.
2563 */
2564 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2565 val == AUDIO_DEVICE_NONE) {
2566 val = AUDIO_DEVICE_OUT_SPEAKER;
2567 }
2568
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002569 /*
2570 * When A2DP is disconnected the
2571 * music playback is paused and the policy manager sends routing=0
2572 * But the audioflingercontinues to write data until standby time
2573 * (3sec). As BT is turned off, the write gets blocked.
2574 * Avoid this by routing audio to speaker until standby.
2575 */
2576 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2577 (val == AUDIO_DEVICE_NONE) &&
2578 !audio_extn_a2dp_is_ready()) {
2579 val = AUDIO_DEVICE_OUT_SPEAKER;
2580 }
2581
2582 /* To avoid a2dp to sco overlapping / BT device improper state
2583 * check with BT lib about a2dp streaming support before routing
2584 */
2585 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2586 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002587 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002588 //combo usecase just by pass a2dp
2589 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2590 bypass_a2dp = true;
2591 } else {
2592 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2593 /* update device to a2dp and don't route as BT returned error
2594 * However it is still possible a2dp routing called because
2595 * of current active device disconnection (like wired headset)
2596 */
2597 out->devices = val;
2598 pthread_mutex_unlock(&out->lock);
2599 pthread_mutex_unlock(&adev->lock);
2600 status = -ENOSYS;
2601 goto routing_fail;
2602 }
2603 }
2604 }
2605
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002606 audio_devices_t new_dev = val;
2607
2608 // Workaround: If routing to an non existing usb device, fail gracefully
2609 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002610 int card;
2611 if (audio_is_usb_out_device(new_dev) &&
2612 (card = get_alive_usb_card(parms)) >= 0) {
2613
2614 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002615 pthread_mutex_unlock(&adev->lock);
2616 pthread_mutex_unlock(&out->lock);
2617 status = -ENOSYS;
2618 goto routing_fail;
2619 }
2620
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002621 /*
2622 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002623 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002624 * the select_devices(). But how do we undo this?
2625 *
2626 * For example, music playback is active on headset (deep-buffer usecase)
2627 * and if we go to ringtones and select a ringtone, low-latency usecase
2628 * will be started on headset+speaker. As we can't enable headset+speaker
2629 * and headset devices at the same time, select_devices() switches the music
2630 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2631 * So when the ringtone playback is completed, how do we undo the same?
2632 *
2633 * We are relying on the out_set_parameters() call on deep-buffer output,
2634 * once the ringtone playback is ended.
2635 * NOTE: We should not check if the current devices are same as new devices.
2636 * Because select_devices() must be called to switch back the music
2637 * playback to headset.
2638 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002639 if (new_dev != AUDIO_DEVICE_NONE) {
2640 bool same_dev = out->devices == new_dev;
2641 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002642
Eric Laurenta7657192014-10-09 21:09:33 -07002643 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002644 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002645 if (adev->mode == AUDIO_MODE_IN_CALL) {
2646 adev->current_call_output = out;
2647 ret = voice_start_call(adev);
2648 }
2649 } else {
2650 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002651 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002652 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002653 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002654
2655 if (!out->standby) {
2656 if (!same_dev) {
2657 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002658 // inform adm before actual routing to prevent glitches.
2659 if (adev->adm_on_routing_change) {
2660 adev->adm_on_routing_change(adev->adm_data,
2661 out->handle);
2662 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002663 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002664 if (!bypass_a2dp) {
2665 select_devices(adev, out->usecase);
2666 } else {
juyuchen9baad392018-06-05 19:02:10 +08002667 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2668 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2669 else
2670 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002671 select_devices(adev, out->usecase);
2672 out->devices = new_dev;
2673 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002674 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002675
2676 // on device switch force swap, lower functions will make sure
2677 // to check if swap is allowed or not.
2678
2679 if (!same_dev)
2680 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002681
2682 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2683 out->a2dp_compress_mute &&
2684 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2685 pthread_mutex_lock(&out->compr_mute_lock);
2686 out->a2dp_compress_mute = false;
2687 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2688 pthread_mutex_unlock(&out->compr_mute_lock);
2689 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002690 }
2691
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002692 }
2693
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002695 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002696
2697 /*handles device and call state changes*/
2698 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002700 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002701
2702 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2703 parse_compress_metadata(out, parms);
2704 }
2705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002706 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002707 ALOGV("%s: exit: code(%d)", __func__, status);
2708 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709}
2710
Haynes Mathew George569b7482017-05-08 14:44:27 -07002711static bool stream_get_parameter_channels(struct str_parms *query,
2712 struct str_parms *reply,
2713 audio_channel_mask_t *supported_channel_masks) {
2714 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002717 size_t i, j;
2718
2719 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2720 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 value[0] = '\0';
2722 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002723 while (supported_channel_masks[i] != 0) {
2724 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2725 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002726 if (!first) {
2727 strcat(value, "|");
2728 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002729 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002730 first = false;
2731 break;
2732 }
2733 }
2734 i++;
2735 }
2736 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002737 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002738 return ret >= 0;
2739}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002740
Haynes Mathew George569b7482017-05-08 14:44:27 -07002741static bool stream_get_parameter_formats(struct str_parms *query,
2742 struct str_parms *reply,
2743 audio_format_t *supported_formats) {
2744 int ret = -1;
2745 char value[256];
2746 int i;
2747
2748 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2749 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002750 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002751 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002752 case AUDIO_FORMAT_PCM_16_BIT:
2753 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2754 break;
2755 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2756 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2757 break;
2758 case AUDIO_FORMAT_PCM_32_BIT:
2759 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2760 break;
2761 default:
2762 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002764 break;
2765 }
2766 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002767 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002768 return ret >= 0;
2769}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002770
Haynes Mathew George569b7482017-05-08 14:44:27 -07002771static bool stream_get_parameter_rates(struct str_parms *query,
2772 struct str_parms *reply,
2773 uint32_t *supported_sample_rates) {
2774
2775 int i;
2776 char value[256];
2777 int ret = -1;
2778 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2779 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002780 value[0] = '\0';
2781 i=0;
2782 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002783 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002784 int avail = sizeof(value) - cursor;
2785 ret = snprintf(value + cursor, avail, "%s%d",
2786 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002787 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002788 if (ret < 0 || ret >= avail) {
2789 // if cursor is at the last element of the array
2790 // overwrite with \0 is duplicate work as
2791 // snprintf already put a \0 in place.
2792 // else
2793 // we had space to write the '|' at value[cursor]
2794 // (which will be overwritten) or no space to fill
2795 // the first element (=> cursor == 0)
2796 value[cursor] = '\0';
2797 break;
2798 }
2799 cursor += ret;
2800 ++i;
2801 }
2802 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2803 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002804 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002805 return ret >= 0;
2806}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002807
Haynes Mathew George569b7482017-05-08 14:44:27 -07002808static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2809{
2810 struct stream_out *out = (struct stream_out *)stream;
2811 struct str_parms *query = str_parms_create_str(keys);
2812 char *str;
2813 struct str_parms *reply = str_parms_create();
2814 bool replied = false;
2815 ALOGV("%s: enter: keys - %s", __func__, keys);
2816
2817 replied |= stream_get_parameter_channels(query, reply,
2818 &out->supported_channel_masks[0]);
2819 replied |= stream_get_parameter_formats(query, reply,
2820 &out->supported_formats[0]);
2821 replied |= stream_get_parameter_rates(query, reply,
2822 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002823 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 str = str_parms_to_str(reply);
2825 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002826 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827 }
2828 str_parms_destroy(query);
2829 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return str;
2832}
2833
2834static uint32_t out_get_latency(const struct audio_stream_out *stream)
2835{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002836 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002838 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2841 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002842 else if ((out->realtime) ||
2843 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002844 // since the buffer won't be filled up faster than realtime,
2845 // return a smaller number
2846 period_ms = (out->af_period_multiplier * out->config.period_size *
2847 1000) / (out->config.rate);
2848 hw_delay = platform_render_latency(out->usecase)/1000;
2849 return period_ms + hw_delay;
2850 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002852 latency = (out->config.period_count * out->config.period_size * 1000) /
2853 (out->config.rate);
2854
2855 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2856 latency += audio_extn_a2dp_get_encoder_latency();
2857
2858 return latency;
2859}
2860
2861static int set_compr_volume(struct audio_stream_out *stream, float left,
2862 float right)
2863{
2864 struct stream_out *out = (struct stream_out *)stream;
2865 int volume[2];
2866 char mixer_ctl_name[128];
2867 struct audio_device *adev = out->dev;
2868 struct mixer_ctl *ctl;
2869 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2870 PCM_PLAYBACK);
2871
2872 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2873 "Compress Playback %d Volume", pcm_device_id);
2874 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2875 if (!ctl) {
2876 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2877 __func__, mixer_ctl_name);
2878 return -EINVAL;
2879 }
2880 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2881 __func__, mixer_ctl_name, left, right);
2882 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2883 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2884 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2885
2886 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887}
2888
2889static int out_set_volume(struct audio_stream_out *stream, float left,
2890 float right)
2891{
Eric Laurenta9024de2013-04-04 09:19:12 -07002892 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002893 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002895 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002896 /* only take left channel into account: the API is for stereo anyway */
2897 out->muted = (left == 0.0f);
2898 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002899 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002900 pthread_mutex_lock(&out->compr_mute_lock);
2901 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2902 if (!out->a2dp_compress_mute)
2903 ret = set_compr_volume(stream, left, right);
2904 out->volume_l = left;
2905 out->volume_r = right;
2906 pthread_mutex_unlock(&out->compr_mute_lock);
2907 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002908 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002909 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2910 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2911 if (!out->standby) {
2912 // if in standby, cached volume will be sent after stream is opened
2913 audio_extn_utils_send_app_type_gain(out->dev,
2914 out->app_type_cfg.app_type,
2915 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002916 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002917 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002918 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 return -ENOSYS;
2921}
2922
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002923// note: this call is safe only if the stream_cb is
2924// removed first in close_output_stream (as is done now).
2925static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2926{
2927 if (!stream || !parms)
2928 return;
2929
2930 struct stream_out *out = (struct stream_out *)stream;
2931 struct audio_device *adev = out->dev;
2932
2933 card_status_t status;
2934 int card;
2935 if (parse_snd_card_status(parms, &card, &status) < 0)
2936 return;
2937
2938 pthread_mutex_lock(&adev->lock);
2939 bool valid_cb = (card == adev->snd_card);
2940 pthread_mutex_unlock(&adev->lock);
2941
2942 if (!valid_cb)
2943 return;
2944
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002945 lock_output_stream(out);
2946 if (out->card_status != status)
2947 out->card_status = status;
2948 pthread_mutex_unlock(&out->lock);
2949
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002950 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2951 use_case_table[out->usecase],
2952 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2953
2954 if (status == CARD_STATUS_OFFLINE)
2955 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002956
2957 return;
2958}
2959
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002960#ifdef NO_AUDIO_OUT
2961static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002962 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002963{
2964 struct stream_out *out = (struct stream_out *)stream;
2965
2966 /* No Output device supported other than BT for playback.
2967 * Sleep for the amount of buffer duration
2968 */
Eric Laurenta1478072015-09-21 17:21:52 -07002969 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002970 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2971 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002972 out_get_sample_rate(&out->stream.common));
2973 pthread_mutex_unlock(&out->lock);
2974 return bytes;
2975}
2976#endif
2977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2979 size_t bytes)
2980{
2981 struct stream_out *out = (struct stream_out *)stream;
2982 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002983 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002984 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
Eric Laurenta1478072015-09-21 17:21:52 -07002986 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002987 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002988 const size_t frame_size = audio_stream_out_frame_size(stream);
2989 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002990
Eric Laurent0e46adf2016-12-16 12:49:24 -08002991 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2992 error_code = ERROR_CODE_WRITE;
2993 goto exit;
2994 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002995
2996 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2997 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002998 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002999 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3000 ret = -EIO;
3001 goto exit;
3002 }
3003 }
3004 }
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003007 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003008 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003011 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003013 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003014 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 goto exit;
3016 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003017
vivek mehta40125092017-08-21 18:48:51 -07003018 // after standby always force set last known cal step
3019 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3020 ALOGD("%s: retry previous failed cal level set", __func__);
3021 send_gain_dep_calibration_l();
3022 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003025 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003026 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003027 if (out->send_new_metadata) {
3028 ALOGVV("send new gapless metadata");
3029 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3030 out->send_new_metadata = 0;
3031 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003032 unsigned int avail;
3033 struct timespec tstamp;
3034 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3035 /* Do not limit write size if the available frames count is unknown */
3036 if (ret != 0) {
3037 avail = bytes;
3038 }
3039 if (avail == 0) {
3040 ret = 0;
3041 } else {
3042 if (avail > bytes) {
3043 avail = bytes;
3044 }
3045 ret = compress_write(out->compr, buffer, avail);
3046 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3047 __func__, avail, ret);
3048 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003049
Eric Laurent6e895242013-09-05 16:10:57 -07003050 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003051 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3052 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003053 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 compress_start(out->compr);
3055 out->playback_started = 1;
3056 out->offload_state = OFFLOAD_STATE_PLAYING;
3057 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003058 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003059 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003060 } else {
3061 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003064 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 return ret;
3066 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003067 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003069 size_t bytes_to_write = bytes;
3070
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 if (out->muted)
3072 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003073 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003074 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003075 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3076 int16_t *src = (int16_t *)buffer;
3077 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003078
Eric Laurentad2dde92017-09-20 18:27:31 -07003079 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3080 out->format != AUDIO_FORMAT_PCM_16_BIT,
3081 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003082
Eric Laurentad2dde92017-09-20 18:27:31 -07003083 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3084 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3085 }
3086 bytes_to_write /= 2;
3087 }
3088 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3089
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003090 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003091 request_out_focus(out, ns);
3092
3093 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3094 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003095 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003096 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003097 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003098
Haynes Mathew George03c40102016-01-29 17:57:48 -08003099 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003100 } else {
3101 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103 }
3104
3105exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003106 // For PCM we always consume the buffer and return #bytes regardless of ret.
3107 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003108 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003109 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003110 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003111
Andy Hung7401c7c2016-09-21 12:41:21 -07003112 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003113 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003114 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3115 ALOGE_IF(out->pcm != NULL,
3116 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003117 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003118 // usleep not guaranteed for values over 1 second but we don't limit here.
3119 }
3120 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 pthread_mutex_unlock(&out->lock);
3123
3124 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003125 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003126 if (sleeptime_us != 0)
3127 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 }
3129 return bytes;
3130}
3131
3132static int out_get_render_position(const struct audio_stream_out *stream,
3133 uint32_t *dsp_frames)
3134{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 struct stream_out *out = (struct stream_out *)stream;
3136 *dsp_frames = 0;
3137 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003138 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003140 unsigned long frames = 0;
3141 // TODO: check return value
3142 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3143 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003144 ALOGVV("%s rendered frames %d sample_rate %d",
3145 __func__, *dsp_frames, out->sample_rate);
3146 }
3147 pthread_mutex_unlock(&out->lock);
3148 return 0;
3149 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003150 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151}
3152
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003153static int out_add_audio_effect(const struct audio_stream *stream __unused,
3154 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155{
3156 return 0;
3157}
3158
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003159static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3160 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161{
3162 return 0;
3163}
3164
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003165static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3166 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003168 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169}
3170
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003171static int out_get_presentation_position(const struct audio_stream_out *stream,
3172 uint64_t *frames, struct timespec *timestamp)
3173{
3174 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003175 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003176 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003177
Eric Laurenta1478072015-09-21 17:21:52 -07003178 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003179
Eric Laurent949a0892013-09-20 09:20:13 -07003180 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3181 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003182 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003183 compress_get_tstamp(out->compr, &dsp_frames,
3184 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003185 // Adjustment accounts for A2DP encoder latency with offload usecases
3186 // Note: Encoder latency is returned in ms.
3187 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3188 unsigned long offset =
3189 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3190 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3191 }
Eric Laurent949a0892013-09-20 09:20:13 -07003192 ALOGVV("%s rendered frames %ld sample_rate %d",
3193 __func__, dsp_frames, out->sample_rate);
3194 *frames = dsp_frames;
3195 ret = 0;
3196 /* this is the best we can do */
3197 clock_gettime(CLOCK_MONOTONIC, timestamp);
3198 }
3199 } else {
3200 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003201 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003202 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3203 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003204 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003205 // This adjustment accounts for buffering after app processor.
3206 // It is based on estimated DSP latency per use case, rather than exact.
3207 signed_frames -=
3208 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3209
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003210 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3211 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3212 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3213 signed_frames -=
3214 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3215 }
3216
Eric Laurent949a0892013-09-20 09:20:13 -07003217 // It would be unusual for this value to be negative, but check just in case ...
3218 if (signed_frames >= 0) {
3219 *frames = signed_frames;
3220 ret = 0;
3221 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003222 }
3223 }
3224 }
3225
3226 pthread_mutex_unlock(&out->lock);
3227
3228 return ret;
3229}
3230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003231static int out_set_callback(struct audio_stream_out *stream,
3232 stream_callback_t callback, void *cookie)
3233{
3234 struct stream_out *out = (struct stream_out *)stream;
3235
3236 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003237 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003238 out->offload_callback = callback;
3239 out->offload_cookie = cookie;
3240 pthread_mutex_unlock(&out->lock);
3241 return 0;
3242}
3243
3244static int out_pause(struct audio_stream_out* stream)
3245{
3246 struct stream_out *out = (struct stream_out *)stream;
3247 int status = -ENOSYS;
3248 ALOGV("%s", __func__);
3249 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003250 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003251 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3252 status = compress_pause(out->compr);
3253 out->offload_state = OFFLOAD_STATE_PAUSED;
3254 }
3255 pthread_mutex_unlock(&out->lock);
3256 }
3257 return status;
3258}
3259
3260static int out_resume(struct audio_stream_out* stream)
3261{
3262 struct stream_out *out = (struct stream_out *)stream;
3263 int status = -ENOSYS;
3264 ALOGV("%s", __func__);
3265 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3266 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003267 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3269 status = compress_resume(out->compr);
3270 out->offload_state = OFFLOAD_STATE_PLAYING;
3271 }
3272 pthread_mutex_unlock(&out->lock);
3273 }
3274 return status;
3275}
3276
3277static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3278{
3279 struct stream_out *out = (struct stream_out *)stream;
3280 int status = -ENOSYS;
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 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3285 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3286 else
3287 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3288 pthread_mutex_unlock(&out->lock);
3289 }
3290 return status;
3291}
3292
3293static int out_flush(struct audio_stream_out* stream)
3294{
3295 struct stream_out *out = (struct stream_out *)stream;
3296 ALOGV("%s", __func__);
3297 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003298 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003299 stop_compressed_output_l(out);
3300 pthread_mutex_unlock(&out->lock);
3301 return 0;
3302 }
3303 return -ENOSYS;
3304}
3305
Eric Laurent0e46adf2016-12-16 12:49:24 -08003306static int out_stop(const struct audio_stream_out* stream)
3307{
3308 struct stream_out *out = (struct stream_out *)stream;
3309 struct audio_device *adev = out->dev;
3310 int ret = -ENOSYS;
3311
3312 ALOGV("%s", __func__);
3313 pthread_mutex_lock(&adev->lock);
3314 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3315 out->playback_started && out->pcm != NULL) {
3316 pcm_stop(out->pcm);
3317 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003318 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003319 }
3320 pthread_mutex_unlock(&adev->lock);
3321 return ret;
3322}
3323
3324static int out_start(const struct audio_stream_out* stream)
3325{
3326 struct stream_out *out = (struct stream_out *)stream;
3327 struct audio_device *adev = out->dev;
3328 int ret = -ENOSYS;
3329
3330 ALOGV("%s", __func__);
3331 pthread_mutex_lock(&adev->lock);
3332 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3333 !out->playback_started && out->pcm != NULL) {
3334 ret = start_output_stream(out);
3335 if (ret == 0) {
3336 out->playback_started = true;
3337 }
3338 }
3339 pthread_mutex_unlock(&adev->lock);
3340 return ret;
3341}
3342
Phil Burkbc991042017-02-24 08:06:44 -08003343/*
3344 * Modify config->period_count based on min_size_frames
3345 */
3346static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3347{
3348 int periodCountRequested = (min_size_frames + config->period_size - 1)
3349 / config->period_size;
3350 int periodCount = MMAP_PERIOD_COUNT_MIN;
3351
3352 ALOGV("%s original config.period_size = %d config.period_count = %d",
3353 __func__, config->period_size, config->period_count);
3354
3355 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3356 periodCount *= 2;
3357 }
3358 config->period_count = periodCount;
3359
3360 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3361}
3362
Phil Burk28c35e52019-03-25 10:23:35 -07003363// Read offset for the positional timestamp from a persistent vendor property.
3364// This is to workaround apparent inaccuracies in the timing information that
3365// is used by the AAudio timing model. The inaccuracies can cause glitches.
3366static int64_t get_mmap_out_time_offset() {
3367 const int32_t kDefaultOffsetMicros = 0;
3368 int32_t mmap_time_offset_micros = property_get_int32(
3369 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3370 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3371 return mmap_time_offset_micros * (int64_t)1000;
3372}
3373
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3375 int32_t min_size_frames,
3376 struct audio_mmap_buffer_info *info)
3377{
3378 struct stream_out *out = (struct stream_out *)stream;
3379 struct audio_device *adev = out->dev;
3380 int ret = 0;
3381 unsigned int offset1;
3382 unsigned int frames1;
3383 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003384 uint32_t mmap_size;
3385 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003386
3387 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003388 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003389 pthread_mutex_lock(&adev->lock);
3390
3391 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003392 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003393 ret = -EINVAL;
3394 goto exit;
3395 }
3396 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003397 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003398 ret = -ENOSYS;
3399 goto exit;
3400 }
3401 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3402 if (out->pcm_device_id < 0) {
3403 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3404 __func__, out->pcm_device_id, out->usecase);
3405 ret = -EINVAL;
3406 goto exit;
3407 }
Phil Burkbc991042017-02-24 08:06:44 -08003408
3409 adjust_mmap_period_count(&out->config, min_size_frames);
3410
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3412 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3413 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3414 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3415 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3416 step = "open";
3417 ret = -ENODEV;
3418 goto exit;
3419 }
3420 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3421 if (ret < 0) {
3422 step = "begin";
3423 goto exit;
3424 }
3425 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003426 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003427 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003428 ret = platform_get_mmap_data_fd(adev->platform,
3429 out->pcm_device_id, 0 /*playback*/,
3430 &info->shared_memory_fd,
3431 &mmap_size);
3432 if (ret < 0) {
3433 // Fall back to non exclusive mode
3434 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3435 } else {
3436 if (mmap_size < buffer_size) {
3437 step = "mmap";
3438 goto exit;
3439 }
3440 // FIXME: indicate exclusive mode support by returning a negative buffer size
3441 info->buffer_size_frames *= -1;
3442 }
3443 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444
3445 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3446 if (ret < 0) {
3447 step = "commit";
3448 goto exit;
3449 }
Phil Burkbc991042017-02-24 08:06:44 -08003450
Phil Burk28c35e52019-03-25 10:23:35 -07003451 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
3452
Phil Burkbc991042017-02-24 08:06:44 -08003453 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454 ret = 0;
3455
3456 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3457 __func__, info->shared_memory_address, info->buffer_size_frames);
3458
3459exit:
3460 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003461 if (out->pcm == NULL) {
3462 ALOGE("%s: %s - %d", __func__, step, ret);
3463 } else {
3464 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003465 pcm_close(out->pcm);
3466 out->pcm = NULL;
3467 }
3468 }
3469 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003470 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003471 return ret;
3472}
3473
3474static int out_get_mmap_position(const struct audio_stream_out *stream,
3475 struct audio_mmap_position *position)
3476{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003477 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003478 struct stream_out *out = (struct stream_out *)stream;
3479 ALOGVV("%s", __func__);
3480 if (position == NULL) {
3481 return -EINVAL;
3482 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003483 lock_output_stream(out);
3484 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3485 out->pcm == NULL) {
3486 ret = -ENOSYS;
3487 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003488 }
3489
3490 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003491 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492 if (ret < 0) {
3493 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003494 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003495 }
Phil Burk28c35e52019-03-25 10:23:35 -07003496 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
3497 + out->mmap_time_offset_nanos;
3498
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003499exit:
3500 pthread_mutex_unlock(&out->lock);
3501 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003502}
3503
3504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505/** audio_stream_in implementation **/
3506static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3507{
3508 struct stream_in *in = (struct stream_in *)stream;
3509
3510 return in->config.rate;
3511}
3512
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003513static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514{
3515 return -ENOSYS;
3516}
3517
3518static size_t in_get_buffer_size(const struct audio_stream *stream)
3519{
3520 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003521 return in->config.period_size * in->af_period_multiplier *
3522 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523}
3524
3525static uint32_t in_get_channels(const struct audio_stream *stream)
3526{
3527 struct stream_in *in = (struct stream_in *)stream;
3528
3529 return in->channel_mask;
3530}
3531
vivek mehta4ed66e62016-04-15 23:33:34 -07003532static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533{
vivek mehta4ed66e62016-04-15 23:33:34 -07003534 struct stream_in *in = (struct stream_in *)stream;
3535 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536}
3537
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003538static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539{
3540 return -ENOSYS;
3541}
3542
3543static int in_standby(struct audio_stream *stream)
3544{
3545 struct stream_in *in = (struct stream_in *)stream;
3546 struct audio_device *adev = in->dev;
3547 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003548 bool do_stop = true;
3549
Eric Laurent994a6932013-07-17 11:51:42 -07003550 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003551
3552 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003553
3554 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003555 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003556 audio_extn_sound_trigger_stop_lab(in);
3557 in->standby = true;
3558 }
3559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003561 if (adev->adm_deregister_stream)
3562 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3563
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003564 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003566 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003567 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003568 in->capture_started = false;
3569 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003570 if (in->pcm) {
3571 pcm_close(in->pcm);
3572 in->pcm = NULL;
3573 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003574 adev->enable_voicerx = false;
3575 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003576 if (do_stop) {
3577 status = stop_input_stream(in);
3578 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003579 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003580 }
3581 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003582 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583 return status;
3584}
3585
Andy Hungd13f0d32017-06-12 13:58:37 -07003586static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003587{
Andy Hungd13f0d32017-06-12 13:58:37 -07003588 struct stream_in *in = (struct stream_in *)stream;
3589
3590 // We try to get the lock for consistency,
3591 // but it isn't necessary for these variables.
3592 // If we're not in standby, we may be blocked on a read.
3593 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3594 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3595 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3596 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3597
3598 if (locked) {
3599 pthread_mutex_unlock(&in->lock);
3600 }
3601
3602 // dump error info
3603 (void)error_log_dump(
3604 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605 return 0;
3606}
3607
3608static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3609{
3610 struct stream_in *in = (struct stream_in *)stream;
3611 struct audio_device *adev = in->dev;
3612 struct str_parms *parms;
3613 char *str;
3614 char value[32];
3615 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003616 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617
Eric Laurent994a6932013-07-17 11:51:42 -07003618 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 parms = str_parms_create_str(kvpairs);
3620
3621 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3622
Eric Laurenta1478072015-09-21 17:21:52 -07003623 lock_input_stream(in);
3624
Eric Laurent150dbfe2013-02-27 14:31:02 -08003625 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 if (ret >= 0) {
3627 val = atoi(value);
3628 /* no audio source uses val == 0 */
3629 if ((in->source != val) && (val != 0)) {
3630 in->source = val;
3631 }
3632 }
3633
3634 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 if (ret >= 0) {
3637 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003638 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003639
3640 // Workaround: If routing to an non existing usb device, fail gracefully
3641 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003642 int card;
3643 if (audio_is_usb_in_device(val) &&
3644 (card = get_alive_usb_card(parms)) >= 0) {
3645
3646 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003647 status = -ENOSYS;
3648 } else {
3649
3650 in->device = val;
3651 /* If recording is in progress, change the tx device to new device */
3652 if (!in->standby) {
3653 ALOGV("update input routing change");
3654 // inform adm before actual routing to prevent glitches.
3655 if (adev->adm_on_routing_change) {
3656 adev->adm_on_routing_change(adev->adm_data,
3657 in->capture_handle);
3658 }
3659 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003660 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003662 }
3663 }
3664
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003666 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667
3668 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003669 ALOGV("%s: exit: status(%d)", __func__, status);
3670 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671}
3672
Haynes Mathew George569b7482017-05-08 14:44:27 -07003673static char* in_get_parameters(const struct audio_stream *stream,
3674 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003676 struct stream_in *in = (struct stream_in *)stream;
3677 struct str_parms *query = str_parms_create_str(keys);
3678 char *str;
3679 struct str_parms *reply = str_parms_create();
3680 bool replied = false;
3681
3682 ALOGV("%s: enter: keys - %s", __func__, keys);
3683 replied |= stream_get_parameter_channels(query, reply,
3684 &in->supported_channel_masks[0]);
3685 replied |= stream_get_parameter_formats(query, reply,
3686 &in->supported_formats[0]);
3687 replied |= stream_get_parameter_rates(query, reply,
3688 &in->supported_sample_rates[0]);
3689 if (replied) {
3690 str = str_parms_to_str(reply);
3691 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003692 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003693 }
3694 str_parms_destroy(query);
3695 str_parms_destroy(reply);
3696 ALOGV("%s: exit: returns - %s", __func__, str);
3697 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698}
3699
Eric Laurent51f3c662018-04-10 18:21:34 -07003700static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701{
Eric Laurent51f3c662018-04-10 18:21:34 -07003702 struct stream_in *in = (struct stream_in *)stream;
3703 char mixer_ctl_name[128];
3704 struct mixer_ctl *ctl;
3705 int ctl_value;
3706
3707 ALOGV("%s: gain %f", __func__, gain);
3708
3709 if (stream == NULL)
3710 return -EINVAL;
3711
3712 /* in_set_gain() only used to silence MMAP capture for now */
3713 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3714 return -ENOSYS;
3715
3716 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3717
3718 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3719 if (!ctl) {
3720 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3721 __func__, mixer_ctl_name);
3722 return -ENOSYS;
3723 }
3724
3725 if (gain < RECORD_GAIN_MIN)
3726 gain = RECORD_GAIN_MIN;
3727 else if (gain > RECORD_GAIN_MAX)
3728 gain = RECORD_GAIN_MAX;
3729 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3730
3731 mixer_ctl_set_value(ctl, 0, ctl_value);
3732 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733}
3734
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003735static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3736{
3737 if (!stream || !parms)
3738 return;
3739
3740 struct stream_in *in = (struct stream_in *)stream;
3741 struct audio_device *adev = in->dev;
3742
3743 card_status_t status;
3744 int card;
3745 if (parse_snd_card_status(parms, &card, &status) < 0)
3746 return;
3747
3748 pthread_mutex_lock(&adev->lock);
3749 bool valid_cb = (card == adev->snd_card);
3750 pthread_mutex_unlock(&adev->lock);
3751
3752 if (!valid_cb)
3753 return;
3754
3755 lock_input_stream(in);
3756 if (in->card_status != status)
3757 in->card_status = status;
3758 pthread_mutex_unlock(&in->lock);
3759
3760 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3761 use_case_table[in->usecase],
3762 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3763
3764 // a better solution would be to report error back to AF and let
3765 // it put the stream to standby
3766 if (status == CARD_STATUS_OFFLINE)
3767 in_standby(&in->stream.common);
3768
3769 return;
3770}
3771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3773 size_t bytes)
3774{
3775 struct stream_in *in = (struct stream_in *)stream;
3776 struct audio_device *adev = in->dev;
3777 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003778 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003779 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780
Eric Laurenta1478072015-09-21 17:21:52 -07003781 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003782 const size_t frame_size = audio_stream_in_frame_size(stream);
3783 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003784
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003785 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003786 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003787 /* Read from sound trigger HAL */
3788 audio_extn_sound_trigger_read(in, buffer, bytes);
3789 pthread_mutex_unlock(&in->lock);
3790 return bytes;
3791 }
3792
Eric Laurent0e46adf2016-12-16 12:49:24 -08003793 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3794 ret = -ENOSYS;
3795 goto exit;
3796 }
3797
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003799 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003801 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 goto exit;
3804 }
3805 in->standby = 0;
3806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807
Andy Hungd13f0d32017-06-12 13:58:37 -07003808 // errors that occur here are read errors.
3809 error_code = ERROR_CODE_READ;
3810
Haynes Mathew George03c40102016-01-29 17:57:48 -08003811 //what's the duration requested by the client?
3812 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3813 in->config.rate;
3814 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003815
Haynes Mathew George03c40102016-01-29 17:57:48 -08003816 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003818 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003819 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003820 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003821 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003822 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003823 if (ret < 0) {
3824 ALOGE("Failed to read w/err %s", strerror(errno));
3825 ret = -errno;
3826 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003827 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3828 if (bytes % 4 == 0) {
3829 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3830 int_buf_stream = buffer;
3831 for (size_t itt=0; itt < bytes/4 ; itt++) {
3832 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003833 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003834 } else {
3835 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3836 ret = -EINVAL;
3837 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003838 }
3839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 }
3841
Haynes Mathew George03c40102016-01-29 17:57:48 -08003842 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 /*
3845 * Instead of writing zeroes here, we could trust the hardware
3846 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003847 * 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 -08003848 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003849 if (ret == 0 && adev->mic_muted &&
3850 !voice_is_in_call_rec_stream(in) &&
3851 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003853 in->frames_muted += frames;
3854 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
3856exit:
3857 pthread_mutex_unlock(&in->lock);
3858
3859 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003860 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 in_standby(&in->stream.common);
3862 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003863 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003864 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003865 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003866 }
3867 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003868 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 }
3870 return bytes;
3871}
3872
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003873static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874{
3875 return 0;
3876}
3877
Andy Hung6ebe5962016-01-15 17:46:57 -08003878static int in_get_capture_position(const struct audio_stream_in *stream,
3879 int64_t *frames, int64_t *time)
3880{
3881 if (stream == NULL || frames == NULL || time == NULL) {
3882 return -EINVAL;
3883 }
3884 struct stream_in *in = (struct stream_in *)stream;
3885 int ret = -ENOSYS;
3886
3887 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003888 // note: ST sessions do not close the alsa pcm driver synchronously
3889 // on standby. Therefore, we may return an error even though the
3890 // pcm stream is still opened.
3891 if (in->standby) {
3892 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3893 "%s stream in standby but pcm not NULL for non ST session", __func__);
3894 goto exit;
3895 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003896 if (in->pcm) {
3897 struct timespec timestamp;
3898 unsigned int avail;
3899 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3900 *frames = in->frames_read + avail;
3901 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3902 ret = 0;
3903 }
3904 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003905exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003906 pthread_mutex_unlock(&in->lock);
3907 return ret;
3908}
3909
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003910static int add_remove_audio_effect(const struct audio_stream *stream,
3911 effect_handle_t effect,
3912 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003914 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003915 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003916 int status = 0;
3917 effect_descriptor_t desc;
3918
3919 status = (*effect)->get_descriptor(effect, &desc);
3920 if (status != 0)
3921 return status;
3922
Eric Laurenta1478072015-09-21 17:21:52 -07003923 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003924 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003925 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003926 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003927 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003928 in->enable_aec != enable &&
3929 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3930 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003931 if (!enable)
3932 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003933 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3934 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3935 adev->enable_voicerx = enable;
3936 struct audio_usecase *usecase;
3937 struct listnode *node;
3938 list_for_each(node, &adev->usecase_list) {
3939 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003940 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003941 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003942 }
3943 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003944 if (!in->standby)
3945 select_devices(in->dev, in->usecase);
3946 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003947 if (in->enable_ns != enable &&
3948 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3949 in->enable_ns = enable;
3950 if (!in->standby)
3951 select_devices(in->dev, in->usecase);
3952 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003953 pthread_mutex_unlock(&in->dev->lock);
3954 pthread_mutex_unlock(&in->lock);
3955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003956 return 0;
3957}
3958
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003959static int in_add_audio_effect(const struct audio_stream *stream,
3960 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961{
Eric Laurent994a6932013-07-17 11:51:42 -07003962 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003963 return add_remove_audio_effect(stream, effect, true);
3964}
3965
3966static int in_remove_audio_effect(const struct audio_stream *stream,
3967 effect_handle_t effect)
3968{
Eric Laurent994a6932013-07-17 11:51:42 -07003969 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003970 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971}
3972
Eric Laurent0e46adf2016-12-16 12:49:24 -08003973static int in_stop(const struct audio_stream_in* stream)
3974{
3975 struct stream_in *in = (struct stream_in *)stream;
3976 struct audio_device *adev = in->dev;
3977
3978 int ret = -ENOSYS;
3979 ALOGV("%s", __func__);
3980 pthread_mutex_lock(&adev->lock);
3981 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3982 in->capture_started && in->pcm != NULL) {
3983 pcm_stop(in->pcm);
3984 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003985 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003986 }
3987 pthread_mutex_unlock(&adev->lock);
3988 return ret;
3989}
3990
3991static int in_start(const struct audio_stream_in* stream)
3992{
3993 struct stream_in *in = (struct stream_in *)stream;
3994 struct audio_device *adev = in->dev;
3995 int ret = -ENOSYS;
3996
3997 ALOGV("%s in %p", __func__, in);
3998 pthread_mutex_lock(&adev->lock);
3999 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4000 !in->capture_started && in->pcm != NULL) {
4001 if (!in->capture_started) {
4002 ret = start_input_stream(in);
4003 if (ret == 0) {
4004 in->capture_started = true;
4005 }
4006 }
4007 }
4008 pthread_mutex_unlock(&adev->lock);
4009 return ret;
4010}
4011
4012static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4013 int32_t min_size_frames,
4014 struct audio_mmap_buffer_info *info)
4015{
4016 struct stream_in *in = (struct stream_in *)stream;
4017 struct audio_device *adev = in->dev;
4018 int ret = 0;
4019 unsigned int offset1;
4020 unsigned int frames1;
4021 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004022 uint32_t mmap_size;
4023 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004024
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004025 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004026 pthread_mutex_lock(&adev->lock);
4027 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004028
Eric Laurent0e46adf2016-12-16 12:49:24 -08004029 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004030 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004031 ret = -EINVAL;
4032 goto exit;
4033 }
4034 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004035 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004036 ALOGV("%s in %p", __func__, in);
4037 ret = -ENOSYS;
4038 goto exit;
4039 }
4040 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4041 if (in->pcm_device_id < 0) {
4042 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4043 __func__, in->pcm_device_id, in->usecase);
4044 ret = -EINVAL;
4045 goto exit;
4046 }
Phil Burkbc991042017-02-24 08:06:44 -08004047
4048 adjust_mmap_period_count(&in->config, min_size_frames);
4049
Eric Laurent0e46adf2016-12-16 12:49:24 -08004050 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4051 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4052 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4053 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4054 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4055 step = "open";
4056 ret = -ENODEV;
4057 goto exit;
4058 }
4059
4060 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4061 if (ret < 0) {
4062 step = "begin";
4063 goto exit;
4064 }
4065 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004066 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004067 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004068 ret = platform_get_mmap_data_fd(adev->platform,
4069 in->pcm_device_id, 1 /*capture*/,
4070 &info->shared_memory_fd,
4071 &mmap_size);
4072 if (ret < 0) {
4073 // Fall back to non exclusive mode
4074 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4075 } else {
4076 if (mmap_size < buffer_size) {
4077 step = "mmap";
4078 goto exit;
4079 }
4080 // FIXME: indicate exclusive mode support by returning a negative buffer size
4081 info->buffer_size_frames *= -1;
4082 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004083
Haynes Mathew George96483a22017-03-28 14:52:47 -07004084 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004085
4086 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4087 if (ret < 0) {
4088 step = "commit";
4089 goto exit;
4090 }
4091
Phil Burkbc991042017-02-24 08:06:44 -08004092 in->standby = false;
4093 ret = 0;
4094
Eric Laurent0e46adf2016-12-16 12:49:24 -08004095 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4096 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004097
4098exit:
4099 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004100 if (in->pcm == NULL) {
4101 ALOGE("%s: %s - %d", __func__, step, ret);
4102 } else {
4103 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004104 pcm_close(in->pcm);
4105 in->pcm = NULL;
4106 }
4107 }
4108 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004109 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004110 return ret;
4111}
4112
4113static int in_get_mmap_position(const struct audio_stream_in *stream,
4114 struct audio_mmap_position *position)
4115{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004116 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004117 struct stream_in *in = (struct stream_in *)stream;
4118 ALOGVV("%s", __func__);
4119 if (position == NULL) {
4120 return -EINVAL;
4121 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004122 lock_input_stream(in);
4123 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4124 in->pcm == NULL) {
4125 ret = -ENOSYS;
4126 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004127 }
4128 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004129 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004130 if (ret < 0) {
4131 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004132 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004133 }
Andy Hungfc044e12017-03-20 09:24:22 -07004134 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004135exit:
4136 pthread_mutex_unlock(&in->lock);
4137 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004138}
4139
jiabin8962a4d2018-03-19 18:21:24 -07004140static int in_get_active_microphones(const struct audio_stream_in *stream,
4141 struct audio_microphone_characteristic_t *mic_array,
4142 size_t *mic_count) {
4143 struct stream_in *in = (struct stream_in *)stream;
4144 struct audio_device *adev = in->dev;
4145 ALOGVV("%s", __func__);
4146
4147 lock_input_stream(in);
4148 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004149 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004150 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004151 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004152 pthread_mutex_unlock(&adev->lock);
4153 pthread_mutex_unlock(&in->lock);
4154
4155 return ret;
4156}
4157
4158static int adev_get_microphones(const struct audio_hw_device *dev,
4159 struct audio_microphone_characteristic_t *mic_array,
4160 size_t *mic_count) {
4161 struct audio_device *adev = (struct audio_device *)dev;
4162 ALOGVV("%s", __func__);
4163
4164 pthread_mutex_lock(&adev->lock);
4165 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4166 pthread_mutex_unlock(&adev->lock);
4167
4168 return ret;
4169}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171static int adev_open_output_stream(struct audio_hw_device *dev,
4172 audio_io_handle_t handle,
4173 audio_devices_t devices,
4174 audio_output_flags_t flags,
4175 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004176 struct audio_stream_out **stream_out,
4177 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178{
4179 struct audio_device *adev = (struct audio_device *)dev;
4180 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004181 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004182 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4183 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4184 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185
Andy Hungd9653bd2017-08-01 19:31:39 -07004186 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4187 return -ENOSYS;
4188 }
4189
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004190 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4191 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 *stream_out = NULL;
4193 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4194
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004195 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 if (devices == AUDIO_DEVICE_NONE)
4198 devices = AUDIO_DEVICE_OUT_SPEAKER;
4199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200 out->flags = flags;
4201 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004202 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004203 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004204 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004205
4206 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004207 if ((is_hdmi || is_usb_dev) &&
4208 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4209 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4210 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004211 audio_format_t req_format = config->format;
4212 audio_channel_mask_t req_channel_mask = config->channel_mask;
4213 uint32_t req_sample_rate = config->sample_rate;
4214
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004215 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004216 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004217 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004218 if (config->sample_rate == 0)
4219 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004220 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004221 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4222 if (config->format == AUDIO_FORMAT_DEFAULT)
4223 config->format = AUDIO_FORMAT_PCM_16_BIT;
4224 } else if (is_usb_dev) {
4225 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4226 &config->format,
4227 &out->supported_formats[0],
4228 MAX_SUPPORTED_FORMATS,
4229 &config->channel_mask,
4230 &out->supported_channel_masks[0],
4231 MAX_SUPPORTED_CHANNEL_MASKS,
4232 &config->sample_rate,
4233 &out->supported_sample_rates[0],
4234 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004235 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004236 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004237 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004238 if (ret != 0) {
4239 // For MMAP NO IRQ, allow conversions in ADSP
4240 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4241 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004242
Eric Laurentab805ee2018-03-30 12:20:38 -07004243 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4244 config->sample_rate = req_sample_rate;
4245 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4246 config->channel_mask = req_channel_mask;
4247 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4248 config->format = req_format;
4249 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004250
Haynes Mathew George569b7482017-05-08 14:44:27 -07004251 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004252 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004253 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004254 if (is_hdmi) {
4255 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4256 out->config = pcm_config_hdmi_multi;
4257 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4258 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4259 out->config = pcm_config_mmap_playback;
4260 out->stream.start = out_start;
4261 out->stream.stop = out_stop;
4262 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4263 out->stream.get_mmap_position = out_get_mmap_position;
4264 } else {
4265 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4266 out->config = pcm_config_hifi;
4267 }
4268
4269 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004270 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004271 if (is_hdmi) {
4272 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4273 audio_bytes_per_sample(out->format));
4274 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004275 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004276 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004277 pthread_mutex_lock(&adev->lock);
4278 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4279 pthread_mutex_unlock(&adev->lock);
4280
4281 // reject offload during card offline to allow
4282 // fallback to s/w paths
4283 if (offline) {
4284 ret = -ENODEV;
4285 goto error_open;
4286 }
4287
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004288 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4289 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4290 ALOGE("%s: Unsupported Offload information", __func__);
4291 ret = -EINVAL;
4292 goto error_open;
4293 }
4294 if (!is_supported_format(config->offload_info.format)) {
4295 ALOGE("%s: Unsupported audio format", __func__);
4296 ret = -EINVAL;
4297 goto error_open;
4298 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004299 out->sample_rate = config->offload_info.sample_rate;
4300 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4301 out->channel_mask = config->offload_info.channel_mask;
4302 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4303 out->channel_mask = config->channel_mask;
4304 else
4305 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4306
4307 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004308
4309 out->compr_config.codec = (struct snd_codec *)
4310 calloc(1, sizeof(struct snd_codec));
4311
4312 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004313
4314 out->stream.set_callback = out_set_callback;
4315 out->stream.pause = out_pause;
4316 out->stream.resume = out_resume;
4317 out->stream.drain = out_drain;
4318 out->stream.flush = out_flush;
4319
4320 out->compr_config.codec->id =
4321 get_snd_codec_id(config->offload_info.format);
4322 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4323 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004324 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 out->compr_config.codec->bit_rate =
4326 config->offload_info.bit_rate;
4327 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004328 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004329 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4330
4331 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4332 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004333
4334 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004335 create_offload_callback_thread(out);
4336 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4337 __func__, config->offload_info.version,
4338 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004339 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4340 switch (config->sample_rate) {
4341 case 0:
4342 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4343 break;
4344 case 8000:
4345 case 16000:
4346 case 48000:
4347 out->sample_rate = config->sample_rate;
4348 break;
4349 default:
4350 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4351 config->sample_rate);
4352 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4353 ret = -EINVAL;
4354 goto error_open;
4355 }
4356 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4357 switch (config->channel_mask) {
4358 case AUDIO_CHANNEL_NONE:
4359 case AUDIO_CHANNEL_OUT_STEREO:
4360 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4361 break;
4362 default:
4363 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4364 config->channel_mask);
4365 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4366 ret = -EINVAL;
4367 goto error_open;
4368 }
4369 switch (config->format) {
4370 case AUDIO_FORMAT_DEFAULT:
4371 case AUDIO_FORMAT_PCM_16_BIT:
4372 out->format = AUDIO_FORMAT_PCM_16_BIT;
4373 break;
4374 default:
4375 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4376 config->format);
4377 config->format = AUDIO_FORMAT_PCM_16_BIT;
4378 ret = -EINVAL;
4379 goto error_open;
4380 }
4381
4382 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004383 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004384 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004385 case 0:
4386 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4387 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004388 case 8000:
4389 case 16000:
4390 case 48000:
4391 out->sample_rate = config->sample_rate;
4392 break;
4393 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004394 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4395 config->sample_rate);
4396 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4397 ret = -EINVAL;
4398 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004399 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004400 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4401 switch (config->channel_mask) {
4402 case AUDIO_CHANNEL_NONE:
4403 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4404 break;
4405 case AUDIO_CHANNEL_OUT_STEREO:
4406 out->channel_mask = config->channel_mask;
4407 break;
4408 default:
4409 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4410 config->channel_mask);
4411 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4412 ret = -EINVAL;
4413 break;
4414 }
4415 switch (config->format) {
4416 case AUDIO_FORMAT_DEFAULT:
4417 out->format = AUDIO_FORMAT_PCM_16_BIT;
4418 break;
4419 case AUDIO_FORMAT_PCM_16_BIT:
4420 out->format = config->format;
4421 break;
4422 default:
4423 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4424 config->format);
4425 config->format = AUDIO_FORMAT_PCM_16_BIT;
4426 ret = -EINVAL;
4427 break;
4428 }
4429 if (ret != 0)
4430 goto error_open;
4431
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004432 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4433 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004434 out->config.rate = out->sample_rate;
4435 out->config.channels =
4436 audio_channel_count_from_out_mask(out->channel_mask);
4437 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004438 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004439 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4440 switch (config->sample_rate) {
4441 case 0:
4442 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4443 break;
4444 case 8000:
4445 case 16000:
4446 case 32000:
4447 case 48000:
4448 out->sample_rate = config->sample_rate;
4449 break;
4450 default:
4451 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4452 config->sample_rate);
4453 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4454 ret = -EINVAL;
4455 break;
4456 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004457 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004458 switch (config->channel_mask) {
4459 case AUDIO_CHANNEL_NONE:
4460 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4461 break;
4462 case AUDIO_CHANNEL_OUT_STEREO:
4463 out->channel_mask = config->channel_mask;
4464 break;
4465 default:
4466 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4467 config->channel_mask);
4468 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4469 ret = -EINVAL;
4470 break;
4471 }
4472 switch (config->format) {
4473 case AUDIO_FORMAT_DEFAULT:
4474 out->format = AUDIO_FORMAT_PCM_16_BIT;
4475 break;
4476 case AUDIO_FORMAT_PCM_16_BIT:
4477 out->format = config->format;
4478 break;
4479 default:
4480 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4481 config->format);
4482 config->format = AUDIO_FORMAT_PCM_16_BIT;
4483 ret = -EINVAL;
4484 break;
4485 }
4486 if (ret != 0)
4487 goto error_open;
4488
vivek mehtaa68fea62017-06-08 19:04:02 -07004489 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004490 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4491 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004492 out->config.rate = out->sample_rate;
4493 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004494 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495 out->sample_rate,
4496 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004497 out->config.channels,
4498 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004499 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004500 out->config.period_size = buffer_size / frame_size;
4501 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4502 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004503 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004504 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004505 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4506 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004507 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004508 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4509 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004510 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004511 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004512 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004513 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004514 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004515 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4516 out->config = pcm_config_mmap_playback;
4517 out->stream.start = out_start;
4518 out->stream.stop = out_stop;
4519 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4520 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004521 } else {
4522 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4523 out->config = pcm_config_low_latency;
4524 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004525
4526 if (config->sample_rate == 0) {
4527 out->sample_rate = out->config.rate;
4528 } else {
4529 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004530 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004531 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4532 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4533 } else {
4534 out->channel_mask = config->channel_mask;
4535 }
4536 if (config->format == AUDIO_FORMAT_DEFAULT)
4537 out->format = audio_format_from_pcm_format(out->config.format);
4538 else if (!audio_is_linear_pcm(config->format)) {
4539 config->format = AUDIO_FORMAT_PCM_16_BIT;
4540 ret = -EINVAL;
4541 goto error_open;
4542 } else {
4543 out->format = config->format;
4544 }
4545
4546 out->config.rate = out->sample_rate;
4547 out->config.channels =
4548 audio_channel_count_from_out_mask(out->channel_mask);
4549 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4550 out->config.format = pcm_format_from_audio_format(out->format);
4551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004552 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004553
4554 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4555 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004556 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004557 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4558 __func__, config->sample_rate, config->format, config->channel_mask);
4559 config->sample_rate = out->sample_rate;
4560 config->format = out->format;
4561 config->channel_mask = out->channel_mask;
4562 ret = -EINVAL;
4563 goto error_open;
4564 }
4565
Andy Hung6fcba9c2014-03-18 11:53:32 -07004566 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4567 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004569 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004570 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004571 adev->primary_output = out;
4572 else {
4573 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004574 ret = -EEXIST;
4575 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004576 }
4577 }
4578
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 /* Check if this usecase is already existing */
4580 pthread_mutex_lock(&adev->lock);
4581 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4582 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004584 ret = -EEXIST;
4585 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004586 }
4587 pthread_mutex_unlock(&adev->lock);
4588
4589 out->stream.common.get_sample_rate = out_get_sample_rate;
4590 out->stream.common.set_sample_rate = out_set_sample_rate;
4591 out->stream.common.get_buffer_size = out_get_buffer_size;
4592 out->stream.common.get_channels = out_get_channels;
4593 out->stream.common.get_format = out_get_format;
4594 out->stream.common.set_format = out_set_format;
4595 out->stream.common.standby = out_standby;
4596 out->stream.common.dump = out_dump;
4597 out->stream.common.set_parameters = out_set_parameters;
4598 out->stream.common.get_parameters = out_get_parameters;
4599 out->stream.common.add_audio_effect = out_add_audio_effect;
4600 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4601 out->stream.get_latency = out_get_latency;
4602 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004603#ifdef NO_AUDIO_OUT
4604 out->stream.write = out_write_for_no_output;
4605#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004606 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004607#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608 out->stream.get_render_position = out_get_render_position;
4609 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004610 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611
Eric Laurent0e46adf2016-12-16 12:49:24 -08004612 if (out->realtime)
4613 out->af_period_multiplier = af_period_multiplier;
4614 else
4615 out->af_period_multiplier = 1;
4616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004618 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004619 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004621 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004622 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004623 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625 config->format = out->stream.common.get_format(&out->stream.common);
4626 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4627 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4628
Kevin Rocarda325aa22018-04-03 09:15:52 -07004629 register_format(out->format, out->supported_formats);
4630 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4631 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4632
Andy Hunga452b0a2017-03-15 14:51:15 -07004633 out->error_log = error_log_create(
4634 ERROR_LOG_ENTRIES,
4635 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4636
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004637 /*
4638 By locking output stream before registering, we allow the callback
4639 to update stream's state only after stream's initial state is set to
4640 adev state.
4641 */
4642 lock_output_stream(out);
4643 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4644 pthread_mutex_lock(&adev->lock);
4645 out->card_status = adev->card_status;
4646 pthread_mutex_unlock(&adev->lock);
4647 pthread_mutex_unlock(&out->lock);
4648
vivek mehta4a824772017-06-08 19:05:49 -07004649 stream_app_type_cfg_init(&out->app_type_cfg);
4650
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004652
Eric Laurent994a6932013-07-17 11:51:42 -07004653 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004655
4656error_open:
4657 free(out);
4658 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004659 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004660 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661}
4662
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004663static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 struct audio_stream_out *stream)
4665{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004666 struct stream_out *out = (struct stream_out *)stream;
4667 struct audio_device *adev = out->dev;
4668
Eric Laurent994a6932013-07-17 11:51:42 -07004669 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004670
4671 // must deregister from sndmonitor first to prevent races
4672 // between the callback and close_stream
4673 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004675 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4676 destroy_offload_callback_thread(out);
4677
4678 if (out->compr_config.codec != NULL)
4679 free(out->compr_config.codec);
4680 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004681
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004682 out->a2dp_compress_mute = false;
4683
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004684 if (adev->voice_tx_output == out)
4685 adev->voice_tx_output = NULL;
4686
Andy Hunga452b0a2017-03-15 14:51:15 -07004687 error_log_destroy(out->error_log);
4688 out->error_log = NULL;
4689
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004690 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004691 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004692 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004694 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695}
4696
4697static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4698{
4699 struct audio_device *adev = (struct audio_device *)dev;
4700 struct str_parms *parms;
4701 char *str;
4702 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004703 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004704 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004705 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004706 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
Joe Onorato188b6222016-03-01 11:02:27 -08004708 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004709
4710 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711
4712 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004713 status = voice_set_parameters(adev, parms);
4714 if (status != 0) {
4715 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 }
4717
4718 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4719 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004720 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4722 adev->bluetooth_nrec = true;
4723 else
4724 adev->bluetooth_nrec = false;
4725 }
4726
4727 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4728 if (ret >= 0) {
4729 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4730 adev->screen_off = false;
4731 else
4732 adev->screen_off = true;
4733 }
4734
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004735 ret = str_parms_get_int(parms, "rotation", &val);
4736 if (ret >= 0) {
4737 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004738 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004739 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004740 // FIXME: note that the code below assumes that the speakers are in the correct placement
4741 // relative to the user when the device is rotated 90deg from its default rotation. This
4742 // assumption is device-specific, not platform-specific like this code.
4743 case 270:
4744 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004745 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004746 break;
4747 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004748 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07004749 camera_rotation = CAMERA_ROTATION_PORTRAIT;
4750 break;
4751 case 90:
4752 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004753 break;
4754 default:
4755 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004756 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004757 }
Eric Laurent03f09432014-03-25 18:09:11 -07004758 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004759 // check and set swap
4760 // - check if orientation changed and speaker active
4761 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07004762 adev->camera_orientation =
4763 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
4764#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07004765 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07004766#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004767 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004768 }
4769
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004770 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4771 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004772 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004773 }
4774
David Linee3fe402017-03-13 10:00:42 -07004775 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4776 if (ret >= 0) {
4777 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004778 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004779 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4780 if (ret >= 0) {
4781 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004782 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004783 }
Eric Laurent99dab492017-06-17 15:19:08 -07004784 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004785 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4786 if (ret >= 0) {
4787 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004788 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004789 }
4790 }
4791 }
4792
4793 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4794 if (ret >= 0) {
4795 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004796 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004797 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4798 if (ret >= 0) {
4799 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004800 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004801 }
Eric Laurent99dab492017-06-17 15:19:08 -07004802 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004803 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4804 if (ret >= 0) {
4805 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004806 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004807 }
4808 }
4809 }
4810
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004811 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004812 audio_extn_ma_set_parameters(adev, parms);
4813
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004814 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4815 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004816 struct audio_usecase *usecase;
4817 struct listnode *node;
4818 list_for_each(node, &adev->usecase_list) {
4819 usecase = node_to_item(node, struct audio_usecase, list);
4820 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004821 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004822 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4823
4824 pthread_mutex_unlock(&adev->lock);
4825 lock_output_stream(usecase->stream.out);
4826 pthread_mutex_lock(&adev->lock);
4827 audio_extn_a2dp_set_handoff_mode(true);
4828 // force device switch to reconfigure encoder
4829 select_devices(adev, usecase->id);
4830 audio_extn_a2dp_set_handoff_mode(false);
4831 pthread_mutex_unlock(&usecase->stream.out->lock);
4832 break;
4833 }
4834 }
4835 }
4836
Eric Laurent5f4ca952018-10-19 17:33:43 -07004837 //FIXME: to be replaced by proper video capture properties API
4838 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
4839 if (ret >= 0) {
4840 int camera_facing = CAMERA_FACING_BACK;
4841 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
4842 camera_facing = CAMERA_FACING_FRONT;
4843 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
4844 camera_facing = CAMERA_FACING_BACK;
4845 else {
4846 ALOGW("%s: invalid camera facing value: %s", __func__, value);
4847 goto done;
4848 }
4849 adev->camera_orientation =
4850 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
4851 struct audio_usecase *usecase;
4852 struct listnode *node;
4853 list_for_each(node, &adev->usecase_list) {
4854 usecase = node_to_item(node, struct audio_usecase, list);
4855 struct stream_in *in = usecase->stream.in;
4856 if (usecase->type == PCM_CAPTURE && in != NULL &&
4857 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
4858 select_devices(adev, in->usecase);
4859 }
4860 }
4861 }
4862
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004863done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004865 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004866 ALOGV("%s: exit with code(%d)", __func__, status);
4867 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004868}
4869
4870static char* adev_get_parameters(const struct audio_hw_device *dev,
4871 const char *keys)
4872{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004873 struct audio_device *adev = (struct audio_device *)dev;
4874 struct str_parms *reply = str_parms_create();
4875 struct str_parms *query = str_parms_create_str(keys);
4876 char *str;
4877
4878 pthread_mutex_lock(&adev->lock);
4879
4880 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004881 audio_extn_a2dp_get_parameters(query, reply);
4882
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004883 str = str_parms_to_str(reply);
4884 str_parms_destroy(query);
4885 str_parms_destroy(reply);
4886
4887 pthread_mutex_unlock(&adev->lock);
4888 ALOGV("%s: exit: returns - %s", __func__, str);
4889 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890}
4891
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004892static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004893{
4894 return 0;
4895}
4896
Haynes Mathew George5191a852013-09-11 14:19:36 -07004897static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4898{
4899 int ret;
4900 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004901
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004902 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4903
Haynes Mathew George5191a852013-09-11 14:19:36 -07004904 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004905 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004906 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004907
Haynes Mathew George5191a852013-09-11 14:19:36 -07004908 return ret;
4909}
4910
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004911static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912{
4913 return -ENOSYS;
4914}
4915
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004916static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4917 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918{
4919 return -ENOSYS;
4920}
4921
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004922static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004923{
4924 return -ENOSYS;
4925}
4926
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004927static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928{
4929 return -ENOSYS;
4930}
4931
4932static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4933{
4934 struct audio_device *adev = (struct audio_device *)dev;
4935
4936 pthread_mutex_lock(&adev->lock);
4937 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004938 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004940 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4941 voice_is_in_call(adev)) {
4942 voice_stop_call(adev);
4943 adev->current_call_output = NULL;
4944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945 }
4946 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004947
4948 audio_extn_extspk_set_mode(adev->extspk, mode);
4949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 return 0;
4951}
4952
4953static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4954{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004955 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004956 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957
Eric Laurent2bafff12016-03-17 12:17:23 -07004958 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004959 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004960 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4961 ret = audio_extn_hfp_set_mic_mute(adev, state);
4962 } else {
4963 ret = voice_set_mic_mute(adev, state);
4964 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004965 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004966 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004967
4968 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004969}
4970
4971static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4972{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004973 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974 return 0;
4975}
4976
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004977static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978 const struct audio_config *config)
4979{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004980 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981
Eric Laurent74b55762017-07-09 17:04:53 -07004982 /* Don't know if USB HIFI in this context so use true to be conservative */
4983 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4984 true /*is_usb_hifi */) != 0)
4985 return 0;
4986
vivek mehtaa68fea62017-06-08 19:04:02 -07004987 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4988 config->sample_rate, config->format,
4989 channel_count,
4990 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991}
4992
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004993static bool adev_input_allow_hifi_record(struct audio_device *adev,
4994 audio_devices_t devices,
4995 audio_input_flags_t flags,
4996 audio_source_t source) {
4997 const bool allowed = true;
4998
4999 if (!audio_is_usb_in_device(devices))
5000 return !allowed;
5001
5002 switch (flags) {
5003 case AUDIO_INPUT_FLAG_NONE:
5004 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5005 break;
5006 default:
5007 return !allowed;
5008 }
5009
5010 switch (source) {
5011 case AUDIO_SOURCE_DEFAULT:
5012 case AUDIO_SOURCE_MIC:
5013 case AUDIO_SOURCE_UNPROCESSED:
5014 break;
5015 default:
5016 return !allowed;
5017 }
5018
5019 switch (adev->mode) {
5020 case 0:
5021 break;
5022 default:
5023 return !allowed;
5024 }
5025
5026 return allowed;
5027}
5028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005029static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005030 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005031 audio_devices_t devices,
5032 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005033 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005034 audio_input_flags_t flags,
5035 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005036 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037{
5038 struct audio_device *adev = (struct audio_device *)dev;
5039 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005040 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005041 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005042 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005043 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005044 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5045 devices,
5046 flags,
5047 source);
Eric Laurent74b55762017-07-09 17:04:53 -07005048 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005049 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005050
Andy Hungd9653bd2017-08-01 19:31:39 -07005051 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5052 return -ENOSYS;
5053 }
5054
Eric Laurent74b55762017-07-09 17:04:53 -07005055 if (!(is_usb_dev && may_use_hifi_record)) {
5056 if (config->sample_rate == 0)
5057 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5058 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5059 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5060 if (config->format == AUDIO_FORMAT_DEFAULT)
5061 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005062
Eric Laurent74b55762017-07-09 17:04:53 -07005063 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5064
5065 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5066 return -EINVAL;
5067 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005069 if (audio_extn_tfa_98xx_is_supported() &&
5070 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005071 return -EINVAL;
5072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5074
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005075 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005076 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005078 in->stream.common.get_sample_rate = in_get_sample_rate;
5079 in->stream.common.set_sample_rate = in_set_sample_rate;
5080 in->stream.common.get_buffer_size = in_get_buffer_size;
5081 in->stream.common.get_channels = in_get_channels;
5082 in->stream.common.get_format = in_get_format;
5083 in->stream.common.set_format = in_set_format;
5084 in->stream.common.standby = in_standby;
5085 in->stream.common.dump = in_dump;
5086 in->stream.common.set_parameters = in_set_parameters;
5087 in->stream.common.get_parameters = in_get_parameters;
5088 in->stream.common.add_audio_effect = in_add_audio_effect;
5089 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5090 in->stream.set_gain = in_set_gain;
5091 in->stream.read = in_read;
5092 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005093 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005094 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005095
5096 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005097 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005099 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005100 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005101 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005102
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005103 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5104 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5105 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5106 /* Force channel config requested to mono if incall
5107 record is being requested for only uplink/downlink */
5108 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5109 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5110 ret = -EINVAL;
5111 goto err_open;
5112 }
5113 }
5114
Haynes Mathew George569b7482017-05-08 14:44:27 -07005115 if (is_usb_dev && may_use_hifi_record) {
5116 /* HiFi record selects an appropriate format, channel, rate combo
5117 depending on sink capabilities*/
5118 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5119 &config->format,
5120 &in->supported_formats[0],
5121 MAX_SUPPORTED_FORMATS,
5122 &config->channel_mask,
5123 &in->supported_channel_masks[0],
5124 MAX_SUPPORTED_CHANNEL_MASKS,
5125 &config->sample_rate,
5126 &in->supported_sample_rates[0],
5127 MAX_SUPPORTED_SAMPLE_RATES);
5128 if (ret != 0) {
5129 ret = -EINVAL;
5130 goto err_open;
5131 }
Eric Laurent74b55762017-07-09 17:04:53 -07005132 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005133 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005134 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005135 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5136 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5137 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5138 bool ret_error = false;
5139 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5140 from HAL is 8_24
5141 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5142 8_24 return error indicating supported format is 8_24
5143 *> In case of any other source requesting 24 bit or float return error
5144 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005145
vivek mehta57ff9b52016-04-28 14:13:08 -07005146 on error flinger will retry with supported format passed
5147 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005148 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005149 config->format = AUDIO_FORMAT_PCM_16_BIT;
5150 ret_error = true;
5151 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5152 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5153 ret_error = true;
5154 }
5155
5156 if (ret_error) {
5157 ret = -EINVAL;
5158 goto err_open;
5159 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005160 }
5161
vivek mehta57ff9b52016-04-28 14:13:08 -07005162 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005163 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005166 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5167 if (config->sample_rate == 0)
5168 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5169 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5170 config->sample_rate != 8000) {
5171 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5172 ret = -EINVAL;
5173 goto err_open;
5174 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005175
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005176 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5177 config->format = AUDIO_FORMAT_PCM_16_BIT;
5178 ret = -EINVAL;
5179 goto err_open;
5180 }
5181
5182 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5183 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005184 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005185 } else if (is_usb_dev && may_use_hifi_record) {
5186 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5187 in->config = pcm_config_audio_capture;
5188 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005189 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5190 config->sample_rate,
5191 config->format,
5192 channel_count,
5193 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005194 in->config.period_size = buffer_size / frame_size;
5195 in->config.rate = config->sample_rate;
5196 in->af_period_multiplier = 1;
5197 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005198 } else {
5199 in->usecase = USECASE_AUDIO_RECORD;
5200 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005201 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005202 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005203#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005204 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005205#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005206 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005207 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005208 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005209 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005210 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5211 config->sample_rate,
5212 config->format,
5213 channel_count,
5214 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005215 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005216 in->config.rate = config->sample_rate;
5217 in->af_period_multiplier = 1;
5218 } else {
5219 // period size is left untouched for rt mode playback
5220 in->config = pcm_config_audio_capture_rt;
5221 in->af_period_multiplier = af_period_multiplier;
5222 }
5223 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5224 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005225 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005226 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5227 in->config = pcm_config_mmap_capture;
5228 in->stream.start = in_start;
5229 in->stream.stop = in_stop;
5230 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5231 in->stream.get_mmap_position = in_get_mmap_position;
5232 in->af_period_multiplier = 1;
5233 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005234 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005235 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005236 (config->sample_rate == 8000 ||
5237 config->sample_rate == 16000 ||
5238 config->sample_rate == 32000 ||
5239 config->sample_rate == 48000) &&
5240 channel_count == 1) {
5241 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5242 in->config = pcm_config_audio_capture;
5243 frame_size = audio_stream_in_frame_size(&in->stream);
5244 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5245 config->sample_rate,
5246 config->format,
5247 channel_count, false /*is_low_latency*/);
5248 in->config.period_size = buffer_size / frame_size;
5249 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5250 in->config.rate = config->sample_rate;
5251 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005252 } else {
5253 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005254 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005255 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5256 config->sample_rate,
5257 config->format,
5258 channel_count,
5259 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005260 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005261 in->config.rate = config->sample_rate;
5262 in->af_period_multiplier = 1;
5263 }
5264 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5265 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005266 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005269 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270
Kevin Rocarda325aa22018-04-03 09:15:52 -07005271
5272 register_format(in->format, in->supported_formats);
5273 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5274 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5275
Andy Hungd13f0d32017-06-12 13:58:37 -07005276 in->error_log = error_log_create(
5277 ERROR_LOG_ENTRIES,
5278 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5279
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005280 /* This stream could be for sound trigger lab,
5281 get sound trigger pcm if present */
5282 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005284 lock_input_stream(in);
5285 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5286 pthread_mutex_lock(&adev->lock);
5287 in->card_status = adev->card_status;
5288 pthread_mutex_unlock(&adev->lock);
5289 pthread_mutex_unlock(&in->lock);
5290
vivek mehta4a824772017-06-08 19:05:49 -07005291 stream_app_type_cfg_init(&in->app_type_cfg);
5292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005294 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295 return 0;
5296
5297err_open:
5298 free(in);
5299 *stream_in = NULL;
5300 return ret;
5301}
5302
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005303static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304 struct audio_stream_in *stream)
5305{
Andy Hungd13f0d32017-06-12 13:58:37 -07005306 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005307 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005308
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005309 // must deregister from sndmonitor first to prevent races
5310 // between the callback and close_stream
5311 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005312 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005313
5314 error_log_destroy(in->error_log);
5315 in->error_log = NULL;
5316
Andy Hung0dbb52b2017-08-09 13:51:38 -07005317 pthread_mutex_destroy(&in->pre_lock);
5318 pthread_mutex_destroy(&in->lock);
5319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005320 free(stream);
5321
5322 return;
5323}
5324
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005325static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005326{
5327 return 0;
5328}
5329
Andy Hung31aca912014-03-20 17:14:59 -07005330/* verifies input and output devices and their capabilities.
5331 *
5332 * This verification is required when enabling extended bit-depth or
5333 * sampling rates, as not all qcom products support it.
5334 *
5335 * Suitable for calling only on initialization such as adev_open().
5336 * It fills the audio_device use_case_table[] array.
5337 *
5338 * Has a side-effect that it needs to configure audio routing / devices
5339 * in order to power up the devices and read the device parameters.
5340 * It does not acquire any hw device lock. Should restore the devices
5341 * back to "normal state" upon completion.
5342 */
5343static int adev_verify_devices(struct audio_device *adev)
5344{
5345 /* enumeration is a bit difficult because one really wants to pull
5346 * the use_case, device id, etc from the hidden pcm_device_table[].
5347 * In this case there are the following use cases and device ids.
5348 *
5349 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5350 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005351 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005352 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5353 * [USECASE_AUDIO_RECORD] = {0, 0},
5354 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5355 * [USECASE_VOICE_CALL] = {2, 2},
5356 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005357 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005358 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5359 */
5360
5361 /* should be the usecases enabled in adev_open_input_stream() */
5362 static const int test_in_usecases[] = {
5363 USECASE_AUDIO_RECORD,
5364 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5365 };
5366 /* should be the usecases enabled in adev_open_output_stream()*/
5367 static const int test_out_usecases[] = {
5368 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5369 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5370 };
5371 static const usecase_type_t usecase_type_by_dir[] = {
5372 PCM_PLAYBACK,
5373 PCM_CAPTURE,
5374 };
5375 static const unsigned flags_by_dir[] = {
5376 PCM_OUT,
5377 PCM_IN,
5378 };
5379
5380 size_t i;
5381 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005382 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005383 char info[512]; /* for possible debug info */
5384
5385 for (dir = 0; dir < 2; ++dir) {
5386 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5387 const unsigned flags_dir = flags_by_dir[dir];
5388 const size_t testsize =
5389 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5390 const int *testcases =
5391 dir ? test_in_usecases : test_out_usecases;
5392 const audio_devices_t audio_device =
5393 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5394
5395 for (i = 0; i < testsize; ++i) {
5396 const audio_usecase_t audio_usecase = testcases[i];
5397 int device_id;
5398 snd_device_t snd_device;
5399 struct pcm_params **pparams;
5400 struct stream_out out;
5401 struct stream_in in;
5402 struct audio_usecase uc_info;
5403 int retval;
5404
5405 pparams = &adev->use_case_table[audio_usecase];
5406 pcm_params_free(*pparams); /* can accept null input */
5407 *pparams = NULL;
5408
5409 /* find the device ID for the use case (signed, for error) */
5410 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5411 if (device_id < 0)
5412 continue;
5413
5414 /* prepare structures for device probing */
5415 memset(&uc_info, 0, sizeof(uc_info));
5416 uc_info.id = audio_usecase;
5417 uc_info.type = usecase_type;
5418 if (dir) {
5419 adev->active_input = &in;
5420 memset(&in, 0, sizeof(in));
5421 in.device = audio_device;
5422 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5423 uc_info.stream.in = &in;
5424 } else {
5425 adev->active_input = NULL;
5426 }
5427 memset(&out, 0, sizeof(out));
5428 out.devices = audio_device; /* only field needed in select_devices */
5429 uc_info.stream.out = &out;
5430 uc_info.devices = audio_device;
5431 uc_info.in_snd_device = SND_DEVICE_NONE;
5432 uc_info.out_snd_device = SND_DEVICE_NONE;
5433 list_add_tail(&adev->usecase_list, &uc_info.list);
5434
5435 /* select device - similar to start_(in/out)put_stream() */
5436 retval = select_devices(adev, audio_usecase);
5437 if (retval >= 0) {
5438 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5439#if LOG_NDEBUG == 0
5440 if (*pparams) {
5441 ALOGV("%s: (%s) card %d device %d", __func__,
5442 dir ? "input" : "output", card_id, device_id);
5443 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005444 } else {
5445 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5446 }
5447#endif
5448 }
5449
5450 /* deselect device - similar to stop_(in/out)put_stream() */
5451 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005452 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005453 /* 2. Disable the rx device */
5454 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005455 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005456 list_remove(&uc_info.list);
5457 }
5458 }
5459 adev->active_input = NULL; /* restore adev state */
5460 return 0;
5461}
5462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463static int adev_close(hw_device_t *device)
5464{
Andy Hung31aca912014-03-20 17:14:59 -07005465 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005466 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005467
5468 if (!adev)
5469 return 0;
5470
5471 pthread_mutex_lock(&adev_init_lock);
5472
5473 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005474 audio_extn_snd_mon_unregister_listener(adev);
5475 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005476 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005477 audio_route_free(adev->audio_route);
5478 free(adev->snd_dev_ref_cnt);
5479 platform_deinit(adev->platform);
5480 audio_extn_extspk_deinit(adev->extspk);
5481 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005482 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005483 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5484 pcm_params_free(adev->use_case_table[i]);
5485 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005486 if (adev->adm_deinit)
5487 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005488 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005489 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005490 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005491
5492 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005493
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005494 return 0;
5495}
5496
Glenn Kasten4f993392014-05-14 07:30:48 -07005497/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5498 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5499 * just that it _might_ work.
5500 */
5501static int period_size_is_plausible_for_low_latency(int period_size)
5502{
5503 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005504 case 48:
5505 case 96:
5506 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005507 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005508 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005509 case 240:
5510 case 320:
5511 case 480:
5512 return 1;
5513 default:
5514 return 0;
5515 }
5516}
5517
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005518static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5519{
5520 int card;
5521 card_status_t status;
5522
5523 if (!parms)
5524 return;
5525
5526 if (parse_snd_card_status(parms, &card, &status) < 0)
5527 return;
5528
5529 pthread_mutex_lock(&adev->lock);
5530 bool valid_cb = (card == adev->snd_card);
5531 if (valid_cb) {
5532 if (adev->card_status != status) {
5533 adev->card_status = status;
5534 platform_snd_card_update(adev->platform, status);
5535 }
5536 }
5537 pthread_mutex_unlock(&adev->lock);
5538 return;
5539}
5540
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005541/* out and adev lock held */
5542static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5543{
5544 struct audio_usecase *uc_info;
5545 float left_p;
5546 float right_p;
5547 audio_devices_t devices;
5548
5549 uc_info = get_usecase_from_list(adev, out->usecase);
5550 if (uc_info == NULL) {
5551 ALOGE("%s: Could not find the usecase (%d) in the list",
5552 __func__, out->usecase);
5553 return -EINVAL;
5554 }
5555
5556 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5557 out->usecase, use_case_table[out->usecase]);
5558
5559 if (restore) {
5560 // restore A2DP device for active usecases and unmute if required
5561 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5562 !is_a2dp_device(uc_info->out_snd_device)) {
5563 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5564 select_devices(adev, uc_info->id);
5565 pthread_mutex_lock(&out->compr_mute_lock);
5566 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5567 (out->a2dp_compress_mute)) {
5568 out->a2dp_compress_mute = false;
5569 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5570 }
5571 pthread_mutex_unlock(&out->compr_mute_lock);
5572 }
5573 } else {
5574 // mute compress stream if suspended
5575 pthread_mutex_lock(&out->compr_mute_lock);
5576 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5577 (!out->a2dp_compress_mute)) {
5578 if (!out->standby) {
5579 ALOGD("%s: selecting speaker and muting stream", __func__);
5580 devices = out->devices;
5581 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5582 left_p = out->volume_l;
5583 right_p = out->volume_r;
5584 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5585 compress_pause(out->compr);
5586 set_compr_volume(&out->stream, 0.0f, 0.0f);
5587 out->a2dp_compress_mute = true;
5588 select_devices(adev, out->usecase);
5589 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5590 compress_resume(out->compr);
5591 out->devices = devices;
5592 out->volume_l = left_p;
5593 out->volume_r = right_p;
5594 }
5595 }
5596 pthread_mutex_unlock(&out->compr_mute_lock);
5597 }
5598 ALOGV("%s: exit", __func__);
5599 return 0;
5600}
5601
5602int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5603{
5604 int ret = 0;
5605
5606 lock_output_stream(out);
5607 pthread_mutex_lock(&adev->lock);
5608
5609 ret = check_a2dp_restore_l(adev, out, restore);
5610
5611 pthread_mutex_unlock(&adev->lock);
5612 pthread_mutex_unlock(&out->lock);
5613 return ret;
5614}
5615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005616static int adev_open(const hw_module_t *module, const char *name,
5617 hw_device_t **device)
5618{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005619 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005620
Eric Laurent2bafff12016-03-17 12:17:23 -07005621 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005622 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005623 pthread_mutex_lock(&adev_init_lock);
5624 if (audio_device_ref_count != 0) {
5625 *device = &adev->device.common;
5626 audio_device_ref_count++;
5627 ALOGV("%s: returning existing instance of adev", __func__);
5628 ALOGV("%s: exit", __func__);
5629 pthread_mutex_unlock(&adev_init_lock);
5630 return 0;
5631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 adev = calloc(1, sizeof(struct audio_device));
5633
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005634 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5637 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5638 adev->device.common.module = (struct hw_module_t *)module;
5639 adev->device.common.close = adev_close;
5640
5641 adev->device.init_check = adev_init_check;
5642 adev->device.set_voice_volume = adev_set_voice_volume;
5643 adev->device.set_master_volume = adev_set_master_volume;
5644 adev->device.get_master_volume = adev_get_master_volume;
5645 adev->device.set_master_mute = adev_set_master_mute;
5646 adev->device.get_master_mute = adev_get_master_mute;
5647 adev->device.set_mode = adev_set_mode;
5648 adev->device.set_mic_mute = adev_set_mic_mute;
5649 adev->device.get_mic_mute = adev_get_mic_mute;
5650 adev->device.set_parameters = adev_set_parameters;
5651 adev->device.get_parameters = adev_get_parameters;
5652 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5653 adev->device.open_output_stream = adev_open_output_stream;
5654 adev->device.close_output_stream = adev_close_output_stream;
5655 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005657 adev->device.close_input_stream = adev_close_input_stream;
5658 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005659 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005660
5661 /* Set the default route before the PCM stream is opened */
5662 pthread_mutex_lock(&adev->lock);
5663 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005664 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005665 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005666 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005667 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005668 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005669 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005670 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005671 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005672 pthread_mutex_unlock(&adev->lock);
5673
5674 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005675 adev->platform = platform_init(adev);
5676 if (!adev->platform) {
5677 free(adev->snd_dev_ref_cnt);
5678 free(adev);
5679 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5680 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005681 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005682 return -EINVAL;
5683 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005684 adev->extspk = audio_extn_extspk_init(adev);
5685
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005686 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5687 if (adev->visualizer_lib == NULL) {
5688 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5689 } else {
5690 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5691 adev->visualizer_start_output =
Aniket Kumar Lata72a3cea2018-04-06 13:56:37 -07005692 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005693 "visualizer_hal_start_output");
5694 adev->visualizer_stop_output =
5695 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5696 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005697 }
5698
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005699 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5700 if (adev->offload_effects_lib == NULL) {
5701 ALOGW("%s: DLOPEN failed for %s", __func__,
5702 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5703 } else {
5704 ALOGV("%s: DLOPEN successful for %s", __func__,
5705 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5706 adev->offload_effects_start_output =
5707 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5708 "offload_effects_bundle_hal_start_output");
5709 adev->offload_effects_stop_output =
5710 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5711 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005712 }
5713
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005714 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5715 if (adev->adm_lib == NULL) {
5716 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5717 } else {
5718 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5719 adev->adm_init = (adm_init_t)
5720 dlsym(adev->adm_lib, "adm_init");
5721 adev->adm_deinit = (adm_deinit_t)
5722 dlsym(adev->adm_lib, "adm_deinit");
5723 adev->adm_register_input_stream = (adm_register_input_stream_t)
5724 dlsym(adev->adm_lib, "adm_register_input_stream");
5725 adev->adm_register_output_stream = (adm_register_output_stream_t)
5726 dlsym(adev->adm_lib, "adm_register_output_stream");
5727 adev->adm_deregister_stream = (adm_deregister_stream_t)
5728 dlsym(adev->adm_lib, "adm_deregister_stream");
5729 adev->adm_request_focus = (adm_request_focus_t)
5730 dlsym(adev->adm_lib, "adm_request_focus");
5731 adev->adm_abandon_focus = (adm_abandon_focus_t)
5732 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005733 adev->adm_set_config = (adm_set_config_t)
5734 dlsym(adev->adm_lib, "adm_set_config");
5735 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5736 dlsym(adev->adm_lib, "adm_request_focus_v2");
5737 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5738 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5739 adev->adm_on_routing_change = (adm_on_routing_change_t)
5740 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005741 }
5742
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005743 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005744 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005747
Andy Hung31aca912014-03-20 17:14:59 -07005748 if (k_enable_extended_precision)
5749 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005750
Glenn Kasten4f993392014-05-14 07:30:48 -07005751 char value[PROPERTY_VALUE_MAX];
5752 int trial;
5753 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5754 trial = atoi(value);
5755 if (period_size_is_plausible_for_low_latency(trial)) {
5756 pcm_config_low_latency.period_size = trial;
5757 pcm_config_low_latency.start_threshold = trial / 4;
5758 pcm_config_low_latency.avail_min = trial / 4;
5759 configured_low_latency_capture_period_size = trial;
5760 }
5761 }
5762 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5763 trial = atoi(value);
5764 if (period_size_is_plausible_for_low_latency(trial)) {
5765 configured_low_latency_capture_period_size = trial;
5766 }
5767 }
5768
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005769 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5770
Eric Laurent5f4ca952018-10-19 17:33:43 -07005771 adev->camera_orientation = CAMERA_DEFAULT;
5772
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005773 // commented as full set of app type cfg is sent from platform
5774 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005775 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005776
5777 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5778 af_period_multiplier = atoi(value);
5779 if (af_period_multiplier < 0) {
5780 af_period_multiplier = 2;
5781 } else if (af_period_multiplier > 4) {
5782 af_period_multiplier = 4;
5783 }
5784 ALOGV("new period_multiplier = %d", af_period_multiplier);
5785 }
5786
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005787 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005788 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005789
vivek mehta1a9b7c02015-06-25 11:49:38 -07005790 pthread_mutex_unlock(&adev_init_lock);
5791
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005792 if (adev->adm_init)
5793 adev->adm_data = adev->adm_init();
5794
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005795 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005796 audio_extn_snd_mon_init();
5797 pthread_mutex_lock(&adev->lock);
5798 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5799 adev->card_status = CARD_STATUS_ONLINE;
5800 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005801 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005802
Eric Laurent2bafff12016-03-17 12:17:23 -07005803 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005804 return 0;
5805}
5806
5807static struct hw_module_methods_t hal_module_methods = {
5808 .open = adev_open,
5809};
5810
5811struct audio_module HAL_MODULE_INFO_SYM = {
5812 .common = {
5813 .tag = HARDWARE_MODULE_TAG,
5814 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5815 .hal_api_version = HARDWARE_HAL_API_VERSION,
5816 .id = AUDIO_HARDWARE_MODULE_ID,
5817 .name = "QCOM Audio HAL",
5818 .author = "Code Aurora Forum",
5819 .methods = &hal_module_methods,
5820 },
5821};