blob: 063768615d5f58f242f8428a9a7febd958edd3f1 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
jiabinad481a72018-07-23 12:03:17 -0700228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
jiabinad481a72018-07-23 12:03:17 -0700242#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
yixuanjiang509f0a72018-09-06 18:37:23 +0800603 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
yixuanjiang509f0a72018-09-06 18:37:23 +0800611 if (usecase->type == PCM_CAPTURE)
612 snd_device = usecase->in_snd_device;
613 else
614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
yixuanjiang6c5e87c2018-08-13 11:50:26 +0800617 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800618 platform_add_backend_name(adev->platform, mixer_path, snd_device);
619 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700620 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700621 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623 ALOGV("%s: exit", __func__);
624 return 0;
625}
626
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800627int disable_audio_route(struct audio_device *adev,
628 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800629{
yixuanjiang509f0a72018-09-06 18:37:23 +0800630 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800631 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800632
633 if (usecase == NULL)
634 return -EINVAL;
635
636 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800637 if (usecase->type == PCM_CAPTURE)
638 snd_device = usecase->in_snd_device;
639 else
640 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641 strcpy(mixer_path, use_case_table[usecase->id]);
yixuanjiang509f0a72018-09-06 18:37:23 +0800642 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700643 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700644 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000645 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800647 ALOGV("%s: exit", __func__);
648 return 0;
649}
650
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800651int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700652 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700654 int i, num_devices = 0;
655 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800656 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800657 if (snd_device < SND_DEVICE_MIN ||
658 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800659 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800660 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700662
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700663 platform_send_audio_calibration(adev->platform, snd_device);
664
vivek mehtade4849c2016-03-03 17:23:38 -0800665 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700666 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700667 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800668 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700669 }
670
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700671 /* due to the possibility of calibration overwrite between listen
672 and audio, notify sound trigger hal before audio calibration is sent */
673 audio_extn_sound_trigger_update_device_status(snd_device,
674 ST_EVENT_SND_DEVICE_BUSY);
675
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700676 if (audio_extn_spkr_prot_is_enabled())
677 audio_extn_spkr_prot_calib_cancel(adev);
678
zhaoyang yin4211fad2015-06-04 21:13:25 +0800679 audio_extn_dsm_feedback_enable(adev, snd_device, true);
680
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700681 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800682 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700686 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800687 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700688 }
689 if (audio_extn_spkr_prot_start_processing(snd_device)) {
690 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800691 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700693 } else if (platform_can_split_snd_device(snd_device,
694 &num_devices,
695 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700696 for (i = 0; i < num_devices; i++) {
697 enable_snd_device(adev, new_snd_devices[i]);
698 }
vivek mehtab6506412015-08-07 16:55:17 -0700699 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800701 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
702 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
703 ALOGE(" %s: Invalid sound device returned", __func__);
704 goto on_error;
705 }
Ed Tam70b5c142016-03-21 19:14:29 -0700706
Eric Laurent2e140aa2016-06-30 17:14:46 -0700707 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700708
709 if (is_a2dp_device(snd_device) &&
710 (audio_extn_a2dp_start_playback() < 0)) {
711 ALOGE("%s: failed to configure A2DP control path", __func__);
712 goto on_error;
713 }
714
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_apply_and_update_path(adev->audio_route, device_name);
716 }
717on_success:
718 adev->snd_dev_ref_cnt[snd_device]++;
719 ret_val = 0;
720on_error:
721 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722}
723
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800724int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700725 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700727 int i, num_devices = 0;
728 snd_device_t new_snd_devices[2];
729
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800730 if (snd_device < SND_DEVICE_MIN ||
731 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800732 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800733 return -EINVAL;
734 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700735 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
736 ALOGE("%s: device ref cnt is already 0", __func__);
737 return -EINVAL;
738 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800739 audio_extn_tfa_98xx_disable_speaker(snd_device);
740
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 adev->snd_dev_ref_cnt[snd_device]--;
742 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800743 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800744
745 if (is_a2dp_device(snd_device))
746 audio_extn_a2dp_stop_playback();
747
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700748 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800749 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700750 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700751 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
752 audio_extn_spkr_prot_is_enabled()) {
753 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700754
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700755 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
756 // and does not use speaker swap. As this code causes a problem with device enable ref
757 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700758 // when speaker device is disabled, reset swap.
759 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700760 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700761
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700762 } else if (platform_can_split_snd_device(snd_device,
763 &num_devices,
764 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700765 for (i = 0; i < num_devices; i++) {
766 disable_snd_device(adev, new_snd_devices[i]);
767 }
vivek mehtab6506412015-08-07 16:55:17 -0700768 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800770 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
771 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
772 ALOGE(" %s: Invalid sound device returned", __func__);
773 return -EINVAL;
774 }
775
Eric Laurent2e140aa2016-06-30 17:14:46 -0700776 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800777 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700778 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700779 audio_extn_sound_trigger_update_device_status(snd_device,
780 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 }
vivek mehtab6506412015-08-07 16:55:17 -0700782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800783 return 0;
784}
785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786/*
787 legend:
788 uc - existing usecase
789 new_uc - new usecase
790 d1, d11, d2 - SND_DEVICE enums
791 a1, a2 - corresponding ANDROID device enums
792 B, B1, B2 - backend strings
793
794case 1
795 uc->dev d1 (a1) B1
796 new_uc->dev d1 (a1), d2 (a2) B1, B2
797
798 resolution: disable and enable uc->dev on d1
799
800case 2
801 uc->dev d1 (a1) B1
802 new_uc->dev d11 (a1) B1
803
804 resolution: need to switch uc since d1 and d11 are related
805 (e.g. speaker and voice-speaker)
806 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
807
808case 3
809 uc->dev d1 (a1) B1
810 new_uc->dev d2 (a2) B2
811
812 resolution: no need to switch uc
813
814case 4
815 uc->dev d1 (a1) B
816 new_uc->dev d2 (a2) B
817
818 resolution: disable enable uc-dev on d2 since backends match
819 we cannot enable two streams on two different devices if they
820 share the same backend. e.g. if offload is on speaker device using
821 QUAD_MI2S backend and a low-latency stream is started on voice-handset
822 using the same backend, offload must also be switched to voice-handset.
823
824case 5
825 uc->dev d1 (a1) B
826 new_uc->dev d1 (a1), d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend.
831
832case 6
833 uc->dev d1 a1 B1
834 new_uc->dev d2 a1 B2
835
836 resolution: no need to switch
837
838case 7
839
840 uc->dev d1 (a1), d2 (a2) B1, B2
841 new_uc->dev d1 B1
842
843 resolution: no need to switch
844
845*/
846static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
847 struct audio_usecase *new_uc,
848 snd_device_t new_snd_device)
849{
850 audio_devices_t a1 = uc->stream.out->devices;
851 audio_devices_t a2 = new_uc->stream.out->devices;
852
853 snd_device_t d1 = uc->out_snd_device;
854 snd_device_t d2 = new_snd_device;
855
856 // Treat as a special case when a1 and a2 are not disjoint
857 if ((a1 != a2) && (a1 & a2)) {
858 snd_device_t d3[2];
859 int num_devices = 0;
860 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
861 &num_devices,
862 d3);
863 if (ret < 0) {
864 if (ret != -ENOSYS) {
865 ALOGW("%s failed to split snd_device %d",
866 __func__,
867 popcount(a1) > 1 ? d1 : d2);
868 }
869 goto end;
870 }
871
872 // NB: case 7 is hypothetical and isn't a practical usecase yet.
873 // But if it does happen, we need to give priority to d2 if
874 // the combo devices active on the existing usecase share a backend.
875 // This is because we cannot have a usecase active on a combo device
876 // and a new usecase requests one device in this combo pair.
877 if (platform_check_backends_match(d3[0], d3[1])) {
878 return d2; // case 5
879 } else {
880 return d1; // case 1
881 }
882 } else {
883 if (platform_check_backends_match(d1, d2)) {
884 return d2; // case 2, 4
885 } else {
886 return d1; // case 6, 3
887 }
888 }
889
890end:
891 return d2; // return whatever was calculated before.
892}
893
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700894static void check_and_route_playback_usecases(struct audio_device *adev,
895 struct audio_usecase *uc_info,
896 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897{
898 struct listnode *node;
899 struct audio_usecase *usecase;
900 bool switch_device[AUDIO_USECASE_MAX];
901 int i, num_uc_to_switch = 0;
902
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700903 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
904 uc_info,
905 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700906
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800907 /* For a2dp device reconfigure all active sessions
908 * with new AFE encoder format based on a2dp state
909 */
910 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700911 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
912 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800913 audio_extn_a2dp_is_force_device_switch()) {
914 force_routing = true;
915 }
916
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 /*
918 * This function is to make sure that all the usecases that are active on
919 * the hardware codec backend are always routed to any one device that is
920 * handled by the hardware codec.
921 * For example, if low-latency and deep-buffer usecases are currently active
922 * on speaker and out_set_parameters(headset) is received on low-latency
923 * output, then we have to make sure deep-buffer is also switched to headset,
924 * because of the limitation that both the devices cannot be enabled
925 * at the same time as they share the same backend.
926 */
927 /* Disable all the usecases on the shared backend other than the
928 specified usecase */
929 for (i = 0; i < AUDIO_USECASE_MAX; i++)
930 switch_device[i] = false;
931
932 list_for_each(node, &adev->usecase_list) {
933 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700934 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
935 continue;
936
937 if (force_routing ||
938 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700939 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
940 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700941 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700944 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900956 }
957 }
958
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700959 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700963 d_device = derive_playback_snd_device(usecase, uc_info,
964 snd_device);
965 enable_snd_device(adev, d_device);
966 /* Update the out_snd_device before enabling the audio route */
967 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 }
969 }
970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700971 /* Re-route all the usecases on the shared backend other than the
972 specified usecase to new snd devices */
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700976 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 }
978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 }
980}
981
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700982static void check_and_route_capture_usecases(struct audio_device *adev,
983 struct audio_usecase *uc_info,
984 snd_device_t snd_device)
985{
986 struct listnode *node;
987 struct audio_usecase *usecase;
988 bool switch_device[AUDIO_USECASE_MAX];
989 int i, num_uc_to_switch = 0;
990
vivek mehta4ed66e62016-04-15 23:33:34 -0700991 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 /*
994 * This function is to make sure that all the active capture usecases
995 * are always routed to the same input sound device.
996 * For example, if audio-record and voice-call usecases are currently
997 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
998 * is received for voice call then we have to make sure that audio-record
999 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1000 * because of the limitation that two devices cannot be enabled
1001 * at the same time if they share the same backend.
1002 */
1003 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1004 switch_device[i] = false;
1005
1006 list_for_each(node, &adev->usecase_list) {
1007 usecase = node_to_item(node, struct audio_usecase, list);
1008 if (usecase->type != PCM_PLAYBACK &&
1009 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001010 usecase->in_snd_device != snd_device &&
1011 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1013 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001014 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001015 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001016 switch_device[usecase->id] = true;
1017 num_uc_to_switch++;
1018 }
1019 }
1020
1021 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 list_for_each(node, &adev->usecase_list) {
1023 usecase = node_to_item(node, struct audio_usecase, list);
1024 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001026 }
1027 }
1028
1029 list_for_each(node, &adev->usecase_list) {
1030 usecase = node_to_item(node, struct audio_usecase, list);
1031 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001032 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001033 }
1034 }
1035
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 /* Re-route all the usecases on the shared backend other than the
1037 specified usecase to new snd devices */
1038 list_for_each(node, &adev->usecase_list) {
1039 usecase = node_to_item(node, struct audio_usecase, list);
1040 /* Update the in_snd_device only before enabling the audio route */
1041 if (switch_device[usecase->id] ) {
1042 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001043 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001044 }
1045 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 }
1047}
1048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001050static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001052 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001053 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054
1055 switch (channels) {
1056 /*
1057 * Do not handle stereo output in Multi-channel cases
1058 * Stereo case is handled in normal playback path
1059 */
1060 case 6:
1061 ALOGV("%s: HDMI supports 5.1", __func__);
1062 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1063 break;
1064 case 8:
1065 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1066 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1067 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1068 break;
1069 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001070 ALOGE("HDMI does not support multi channel playback");
1071 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072 break;
1073 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075}
1076
Andy Hung18859412017-08-09 11:47:21 -07001077static ssize_t read_usb_sup_sample_rates(bool is_playback,
1078 uint32_t *supported_sample_rates,
1079 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001081 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1082 supported_sample_rates,
1083 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001084#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001085 for (ssize_t i=0; i<count; i++) {
1086 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1087 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001088 }
1089#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001090 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001091}
1092
Haynes Mathew George569b7482017-05-08 14:44:27 -07001093static int read_usb_sup_channel_masks(bool is_playback,
1094 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001095 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001096{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001097 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001098 int channel_count;
1099 uint32_t num_masks = 0;
1100 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1101 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001102 }
Eric Laurent74b55762017-07-09 17:04:53 -07001103 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001104 // start from 2 channels as framework currently doesn't support mono.
1105 // TODO: consider only supporting channel index masks beyond stereo here.
1106 for (channel_count = FCC_2;
1107 channel_count <= channels && num_masks < max_masks;
1108 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001109 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1110 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001111 for (channel_count = FCC_2;
1112 channel_count <= channels && num_masks < max_masks;
1113 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001114 supported_channel_masks[num_masks++] =
1115 audio_channel_mask_for_index_assignment_from_count(channel_count);
1116 }
1117 } else {
1118 // For capture we report all supported channel masks from 1 channel up.
1119 channel_count = MIN_CHANNEL_COUNT;
1120 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1121 // indexed mask
1122 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1123 supported_channel_masks[num_masks++] =
1124 audio_channel_in_mask_from_count(channel_count);
1125 }
1126 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001127#ifdef NDEBUG
1128 for (size_t i = 0; i < num_masks; ++i) {
1129 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1130 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1131 }
1132#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001133 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001134}
1135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001136static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001137 audio_format_t *supported_formats,
1138 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001139{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001140 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001141 switch (bitwidth) {
1142 case 24:
1143 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001144 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001145 break;
1146 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001148 break;
1149 case 16:
1150 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001151 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001152 break;
1153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001154 ALOGV("%s: %s supported format %d", __func__,
1155 is_playback ? "P" : "C", bitwidth);
1156 return 1;
1157}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001158
Haynes Mathew George569b7482017-05-08 14:44:27 -07001159static int read_usb_sup_params_and_compare(bool is_playback,
1160 audio_format_t *format,
1161 audio_format_t *supported_formats,
1162 uint32_t max_formats,
1163 audio_channel_mask_t *mask,
1164 audio_channel_mask_t *supported_channel_masks,
1165 uint32_t max_masks,
1166 uint32_t *rate,
1167 uint32_t *supported_sample_rates,
1168 uint32_t max_rates) {
1169 int ret = 0;
1170 int num_formats;
1171 int num_masks;
1172 int num_rates;
1173 int i;
1174
1175 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1176 max_formats);
1177 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1178 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001179
Haynes Mathew George569b7482017-05-08 14:44:27 -07001180 num_rates = read_usb_sup_sample_rates(is_playback,
1181 supported_sample_rates, max_rates);
1182
1183#define LUT(table, len, what, dflt) \
1184 for (i=0; i<len && (table[i] != what); i++); \
1185 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1186
1187 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1188 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1189 LUT(supported_sample_rates, num_rates, *rate, 0);
1190
1191#undef LUT
1192 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001193}
1194
Andy Hungd9653bd2017-08-01 19:31:39 -07001195static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1196{
1197 // Check if usb is ready.
1198 // The usb device may have been removed quickly after insertion and hence
1199 // no longer available. This will show up as empty channel masks, or rates.
1200
1201 pthread_mutex_lock(&adev->lock);
1202 uint32_t supported_sample_rate;
1203
1204 // we consider usb ready if we can fetch at least one sample rate.
1205 const bool ready = read_usb_sup_sample_rates(
1206 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1207 pthread_mutex_unlock(&adev->lock);
1208 return ready;
1209}
1210
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001211static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1212{
1213 struct audio_usecase *usecase;
1214 struct listnode *node;
1215
1216 list_for_each(node, &adev->usecase_list) {
1217 usecase = node_to_item(node, struct audio_usecase, list);
1218 if (usecase->type == VOICE_CALL) {
1219 ALOGV("%s: usecase id %d", __func__, usecase->id);
1220 return usecase->id;
1221 }
1222 }
1223 return USECASE_INVALID;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->id == uc_id)
1235 return usecase;
1236 }
1237 return NULL;
1238}
1239
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001240static bool force_device_switch(struct audio_usecase *usecase)
1241{
1242 if (usecase->stream.out == NULL) {
1243 ALOGE("%s: stream.out is NULL", __func__);
1244 return false;
1245 }
1246
1247 // Force all A2DP output devices to reconfigure for proper AFE encode format
1248 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1249 // in suspended state, hence try to trigger a retry when we again get a routing request.
1250 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1251 audio_extn_a2dp_is_force_device_switch()) {
1252 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1253 return true;
1254 }
1255
1256 return false;
1257}
1258
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001259int select_devices(struct audio_device *adev,
1260 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001262 snd_device_t out_snd_device = SND_DEVICE_NONE;
1263 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001264 struct audio_usecase *usecase = NULL;
1265 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001266 struct audio_usecase *hfp_usecase = NULL;
1267 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001268 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001269 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001270 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1271 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 usecase = get_usecase_from_list(adev, uc_id);
1274 if (usecase == NULL) {
1275 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001279 if ((usecase->type == VOICE_CALL) ||
1280 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001281 out_snd_device = platform_get_output_snd_device(adev->platform,
1282 usecase->stream.out->devices);
1283 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->devices = usecase->stream.out->devices;
1285 } else {
1286 /*
1287 * If the voice call is active, use the sound devices of voice call usecase
1288 * so that it would not result any device switch. All the usecases will
1289 * be switched to new device when select_devices() is called for voice call
1290 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001291 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001292 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001293 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001294 vc_usecase = get_usecase_from_list(adev,
1295 get_voice_usecase_id_from_list(adev));
1296 if ((vc_usecase != NULL) &&
1297 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1298 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 in_snd_device = vc_usecase->in_snd_device;
1300 out_snd_device = vc_usecase->out_snd_device;
1301 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001302 } else if (audio_extn_hfp_is_active(adev)) {
1303 hfp_ucid = audio_extn_hfp_get_usecase();
1304 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1305 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1306 in_snd_device = hfp_usecase->in_snd_device;
1307 out_snd_device = hfp_usecase->out_snd_device;
1308 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 }
1310 if (usecase->type == PCM_PLAYBACK) {
1311 usecase->devices = usecase->stream.out->devices;
1312 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001313 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001314 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001318
1319 if (voip_usecase)
1320 voip_out = voip_usecase->stream.out;
1321
1322 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001323 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001324 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001325 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001326 select_devices(adev, adev->active_input->usecase);
1327 }
1328 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 } else if (usecase->type == PCM_CAPTURE) {
1330 usecase->devices = usecase->stream.in->device;
1331 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001332 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001333 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001334 if (adev->active_input &&
1335 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1336 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001337
1338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
1340
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001341 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001342 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1343 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 } else if (voip_usecase) {
1345 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001346 } else if (adev->primary_output) {
1347 out_device = adev->primary_output->devices;
1348 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001349 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001350 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001351 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 }
1353 }
1354
1355 if (out_snd_device == usecase->out_snd_device &&
1356 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001357 if (!force_device_switch(usecase))
1358 return 0;
1359 }
1360
1361 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1362 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1363 return 0;
1364 }
1365
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001366 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1367 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001368 (!audio_extn_a2dp_is_ready())) {
1369 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001370 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1371 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1372 else
1373 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 }
1375
juyuchen66c4ecf2018-08-06 15:39:34 +08001376 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1377 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1378 }
1379
Eric Laurent2bafff12016-03-17 12:17:23 -07001380 if (out_snd_device != SND_DEVICE_NONE &&
1381 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1382 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1383 __func__,
1384 use_case_table[uc_id],
1385 adev->last_logged_snd_device[uc_id][0],
1386 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1387 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1388 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1389 -1,
1390 out_snd_device,
1391 platform_get_snd_device_name(out_snd_device),
1392 platform_get_snd_device_acdb_id(out_snd_device));
1393 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1394 }
1395 if (in_snd_device != SND_DEVICE_NONE &&
1396 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1397 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1398 __func__,
1399 use_case_table[uc_id],
1400 adev->last_logged_snd_device[uc_id][1],
1401 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1402 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1403 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1404 -1,
1405 in_snd_device,
1406 platform_get_snd_device_name(in_snd_device),
1407 platform_get_snd_device_acdb_id(in_snd_device));
1408 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1409 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411 /*
1412 * Limitation: While in call, to do a device switch we need to disable
1413 * and enable both RX and TX devices though one of them is same as current
1414 * device.
1415 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001416 if ((usecase->type == VOICE_CALL) &&
1417 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1418 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001419 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001420 /* Disable sidetone only if voice call already exists */
1421 if (voice_is_call_state_active(adev))
1422 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001423 }
1424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425 /* Disable current sound devices */
1426 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001427 disable_audio_route(adev, usecase);
1428 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001429 }
1430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001432 disable_audio_route(adev, usecase);
1433 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 }
1435
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001436 /* Applicable only on the targets that has external modem.
1437 * New device information should be sent to modem before enabling
1438 * the devices to reduce in-call device switch time.
1439 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001440 if ((usecase->type == VOICE_CALL) &&
1441 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1442 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001443 status = platform_switch_voice_call_enable_device_config(adev->platform,
1444 out_snd_device,
1445 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001446 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 /* Enable new sound devices */
1449 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001450 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001451 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1452 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001453 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001454 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 }
1456
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001457 if (in_snd_device != SND_DEVICE_NONE) {
1458 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001459 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
Eric Laurentb23d5282013-05-14 15:27:20 -07001462 if (usecase->type == VOICE_CALL)
1463 status = platform_switch_voice_call_device_post(adev->platform,
1464 out_snd_device,
1465 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001466
sangwoo170731f2013-06-08 15:36:36 +09001467 usecase->in_snd_device = in_snd_device;
1468 usecase->out_snd_device = out_snd_device;
1469
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001470 audio_extn_tfa_98xx_set_mode();
1471
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001472 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001473
Jasmine Cha70771b62018-05-15 15:02:43 +08001474 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001475
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001476 /* Applicable only on the targets that has external modem.
1477 * Enable device command should be sent to modem only after
1478 * enabling voice call mixer controls
1479 */
vivek mehta765eb642015-08-07 19:46:06 -07001480 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001481 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1482 out_snd_device,
1483 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001484 /* Enable sidetone only if voice call already exists */
1485 if (voice_is_call_state_active(adev))
1486 voice_set_sidetone(adev, out_snd_device, true);
1487 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001488
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001489 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001490 struct stream_out *voip_out = voip_usecase->stream.out;
1491 audio_extn_utils_send_app_type_gain(adev,
1492 voip_out->app_type_cfg.app_type,
1493 &voip_out->app_type_cfg.gain[0]);
1494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 return status;
1496}
1497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498static int stop_input_stream(struct stream_in *in)
1499{
1500 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501 struct audio_usecase *uc_info;
1502 struct audio_device *adev = in->dev;
1503
Eric Laurent994a6932013-07-17 11:51:42 -07001504 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001505 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001506
1507 if (adev->active_input) {
1508 if (adev->active_input->usecase == in->usecase) {
1509 adev->active_input = NULL;
1510 } else {
1511 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1512 __func__,
1513 use_case_table[adev->active_input->usecase],
1514 use_case_table[in->usecase]);
1515 }
1516 }
1517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 uc_info = get_usecase_from_list(adev, in->usecase);
1519 if (uc_info == NULL) {
1520 ALOGE("%s: Could not find the usecase (%d) in the list",
1521 __func__, in->usecase);
1522 return -EINVAL;
1523 }
1524
vivek mehta781065c2017-04-04 12:55:01 -07001525 /* Close in-call recording streams */
1526 voice_check_and_stop_incall_rec_usecase(adev, in);
1527
Eric Laurent150dbfe2013-02-27 14:31:02 -08001528 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001529 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530
1531 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001532 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001534 list_remove(&uc_info->list);
1535 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001536
Eric Laurent994a6932013-07-17 11:51:42 -07001537 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538 return ret;
1539}
1540
1541int start_input_stream(struct stream_in *in)
1542{
1543 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001544 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545 struct audio_usecase *uc_info;
1546 struct audio_device *adev = in->dev;
1547
Eric Laurent994a6932013-07-17 11:51:42 -07001548 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001549
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001550 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1551 return -EIO;
1552
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001553 if (in->card_status == CARD_STATUS_OFFLINE ||
1554 adev->card_status == CARD_STATUS_OFFLINE) {
1555 ALOGW("in->card_status or adev->card_status offline, try again");
1556 ret = -EAGAIN;
1557 goto error_config;
1558 }
1559
vivek mehta781065c2017-04-04 12:55:01 -07001560 /* Check if source matches incall recording usecase criteria */
1561 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1562 if (ret)
1563 goto error_config;
1564 else
1565 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1566
Eric Laurentb23d5282013-05-14 15:27:20 -07001567 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 if (in->pcm_device_id < 0) {
1569 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1570 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001571 ret = -EINVAL;
1572 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001574
1575 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1577 uc_info->id = in->usecase;
1578 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001579 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 uc_info->devices = in->device;
1581 uc_info->in_snd_device = SND_DEVICE_NONE;
1582 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001583
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001584 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001585
Wei Wangf4837d52017-11-21 14:51:20 -08001586 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001587 audio_extn_perf_lock_acquire();
1588
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurent0e46adf2016-12-16 12:49:24 -08001591 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001592 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001593 ALOGE("%s: pcm stream not ready", __func__);
1594 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001595 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001596 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001597 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001598 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1599 goto error_open;
1600 }
1601 } else {
1602 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1603 unsigned int pcm_open_retry_count = 0;
1604
1605 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1606 flags |= PCM_MMAP | PCM_NOIRQ;
1607 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1608 } else if (in->realtime) {
1609 flags |= PCM_MMAP | PCM_NOIRQ;
1610 }
1611
1612 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1613 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1614
1615 while (1) {
1616 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1617 flags, &in->config);
1618 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1619 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1620 if (in->pcm != NULL) {
1621 pcm_close(in->pcm);
1622 in->pcm = NULL;
1623 }
1624 if (pcm_open_retry_count-- == 0) {
1625 ret = -EIO;
1626 goto error_open;
1627 }
1628 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1629 continue;
1630 }
1631 break;
1632 }
1633
1634 ALOGV("%s: pcm_prepare", __func__);
1635 ret = pcm_prepare(in->pcm);
1636 if (ret < 0) {
1637 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001638 pcm_close(in->pcm);
1639 in->pcm = NULL;
1640 goto error_open;
1641 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001642 if (in->realtime) {
1643 ret = pcm_start(in->pcm);
1644 if (ret < 0) {
1645 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1646 pcm_close(in->pcm);
1647 in->pcm = NULL;
1648 goto error_open;
1649 }
1650 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001651 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001652 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001653 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001654 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001655 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001656
Eric Laurent0e46adf2016-12-16 12:49:24 -08001657 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001658
1659error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001660 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001661 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001662 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001663
1664error_config:
1665 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001666 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001667 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668}
1669
Eric Laurenta1478072015-09-21 17:21:52 -07001670void lock_input_stream(struct stream_in *in)
1671{
1672 pthread_mutex_lock(&in->pre_lock);
1673 pthread_mutex_lock(&in->lock);
1674 pthread_mutex_unlock(&in->pre_lock);
1675}
1676
1677void lock_output_stream(struct stream_out *out)
1678{
1679 pthread_mutex_lock(&out->pre_lock);
1680 pthread_mutex_lock(&out->lock);
1681 pthread_mutex_unlock(&out->pre_lock);
1682}
1683
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001684/* must be called with out->lock locked */
1685static int send_offload_cmd_l(struct stream_out* out, int command)
1686{
1687 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1688
1689 ALOGVV("%s %d", __func__, command);
1690
1691 cmd->cmd = command;
1692 list_add_tail(&out->offload_cmd_list, &cmd->node);
1693 pthread_cond_signal(&out->offload_cond);
1694 return 0;
1695}
1696
1697/* must be called iwth out->lock locked */
1698static void stop_compressed_output_l(struct stream_out *out)
1699{
1700 out->offload_state = OFFLOAD_STATE_IDLE;
1701 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001702 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 if (out->compr != NULL) {
1704 compress_stop(out->compr);
1705 while (out->offload_thread_blocked) {
1706 pthread_cond_wait(&out->cond, &out->lock);
1707 }
1708 }
1709}
1710
1711static void *offload_thread_loop(void *context)
1712{
1713 struct stream_out *out = (struct stream_out *) context;
1714 struct listnode *item;
1715
1716 out->offload_state = OFFLOAD_STATE_IDLE;
1717 out->playback_started = 0;
1718
1719 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1720 set_sched_policy(0, SP_FOREGROUND);
1721 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1722
1723 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001724 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001725 for (;;) {
1726 struct offload_cmd *cmd = NULL;
1727 stream_callback_event_t event;
1728 bool send_callback = false;
1729
1730 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1731 __func__, list_empty(&out->offload_cmd_list),
1732 out->offload_state);
1733 if (list_empty(&out->offload_cmd_list)) {
1734 ALOGV("%s SLEEPING", __func__);
1735 pthread_cond_wait(&out->offload_cond, &out->lock);
1736 ALOGV("%s RUNNING", __func__);
1737 continue;
1738 }
1739
1740 item = list_head(&out->offload_cmd_list);
1741 cmd = node_to_item(item, struct offload_cmd, node);
1742 list_remove(item);
1743
1744 ALOGVV("%s STATE %d CMD %d out->compr %p",
1745 __func__, out->offload_state, cmd->cmd, out->compr);
1746
1747 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1748 free(cmd);
1749 break;
1750 }
1751
1752 if (out->compr == NULL) {
1753 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001754 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 pthread_cond_signal(&out->cond);
1756 continue;
1757 }
1758 out->offload_thread_blocked = true;
1759 pthread_mutex_unlock(&out->lock);
1760 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001761 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1763 compress_wait(out->compr, -1);
1764 send_callback = true;
1765 event = STREAM_CBK_EVENT_WRITE_READY;
1766 break;
1767 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001768 compress_next_track(out->compr);
1769 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001770 send_callback = true;
1771 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001772 /* Resend the metadata for next iteration */
1773 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 break;
1775 case OFFLOAD_CMD_DRAIN:
1776 compress_drain(out->compr);
1777 send_callback = true;
1778 event = STREAM_CBK_EVENT_DRAIN_READY;
1779 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001780 case OFFLOAD_CMD_ERROR:
1781 send_callback = true;
1782 event = STREAM_CBK_EVENT_ERROR;
1783 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001784 default:
1785 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1786 break;
1787 }
Eric Laurenta1478072015-09-21 17:21:52 -07001788 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001789 out->offload_thread_blocked = false;
1790 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001791 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001792 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001793 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 free(cmd);
1796 }
1797
1798 pthread_cond_signal(&out->cond);
1799 while (!list_empty(&out->offload_cmd_list)) {
1800 item = list_head(&out->offload_cmd_list);
1801 list_remove(item);
1802 free(node_to_item(item, struct offload_cmd, node));
1803 }
1804 pthread_mutex_unlock(&out->lock);
1805
1806 return NULL;
1807}
1808
1809static int create_offload_callback_thread(struct stream_out *out)
1810{
1811 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1812 list_init(&out->offload_cmd_list);
1813 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1814 offload_thread_loop, out);
1815 return 0;
1816}
1817
1818static int destroy_offload_callback_thread(struct stream_out *out)
1819{
Eric Laurenta1478072015-09-21 17:21:52 -07001820 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001821 stop_compressed_output_l(out);
1822 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1823
1824 pthread_mutex_unlock(&out->lock);
1825 pthread_join(out->offload_thread, (void **) NULL);
1826 pthread_cond_destroy(&out->offload_cond);
1827
1828 return 0;
1829}
1830
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831static bool allow_hdmi_channel_config(struct audio_device *adev)
1832{
1833 struct listnode *node;
1834 struct audio_usecase *usecase;
1835 bool ret = true;
1836
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1840 /*
1841 * If voice call is already existing, do not proceed further to avoid
1842 * disabling/enabling both RX and TX devices, CSD calls, etc.
1843 * Once the voice call done, the HDMI channels can be configured to
1844 * max channels of remaining use cases.
1845 */
1846 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001847 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001848 __func__);
1849 ret = false;
1850 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001851 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1852 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001853 "no change in HDMI channels", __func__);
1854 ret = false;
1855 break;
1856 }
1857 }
1858 }
1859 return ret;
1860}
1861
1862static int check_and_set_hdmi_channels(struct audio_device *adev,
1863 unsigned int channels)
1864{
1865 struct listnode *node;
1866 struct audio_usecase *usecase;
1867
1868 /* Check if change in HDMI channel config is allowed */
1869 if (!allow_hdmi_channel_config(adev))
1870 return 0;
1871
1872 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001873 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001874 return 0;
1875 }
1876
1877 platform_set_hdmi_channels(adev->platform, channels);
1878 adev->cur_hdmi_channels = channels;
1879
1880 /*
1881 * Deroute all the playback streams routed to HDMI so that
1882 * the back end is deactivated. Note that backend will not
1883 * be deactivated if any one stream is connected to it.
1884 */
1885 list_for_each(node, &adev->usecase_list) {
1886 usecase = node_to_item(node, struct audio_usecase, list);
1887 if (usecase->type == PCM_PLAYBACK &&
1888 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001889 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001890 }
1891 }
1892
1893 /*
1894 * Enable all the streams disabled above. Now the HDMI backend
1895 * will be activated with new channel configuration
1896 */
1897 list_for_each(node, &adev->usecase_list) {
1898 usecase = node_to_item(node, struct audio_usecase, list);
1899 if (usecase->type == PCM_PLAYBACK &&
1900 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001901 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001902 }
1903 }
1904
1905 return 0;
1906}
1907
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001908static int check_and_set_usb_service_interval(struct audio_device *adev,
1909 struct audio_usecase *uc_info,
1910 bool min)
1911{
1912 struct listnode *node;
1913 struct audio_usecase *usecase;
1914 bool switch_usecases = false;
1915 bool reconfig = false;
1916
1917 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1918 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1919 return -1;
1920
1921 /* set if the valid usecase do not already exist */
1922 list_for_each(node, &adev->usecase_list) {
1923 usecase = node_to_item(node, struct audio_usecase, list);
1924 if (usecase->type == PCM_PLAYBACK &&
1925 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1926 switch (usecase->id) {
1927 case USECASE_AUDIO_PLAYBACK_MMAP:
1928 case USECASE_AUDIO_PLAYBACK_ULL:
1929 // cannot reconfig while mmap/ull is present.
1930 return -1;
1931 default:
1932 switch_usecases = true;
1933 break;
1934 }
1935 }
1936 if (switch_usecases)
1937 break;
1938 }
1939 /*
1940 * client can try to set service interval in start_output_stream
1941 * to min or to 0 (i.e reset) in stop_output_stream .
1942 */
1943 unsigned long service_interval =
1944 audio_extn_usb_find_service_interval(min, true /*playback*/);
1945 int ret = platform_set_usb_service_interval(adev->platform,
1946 true /*playback*/,
1947 service_interval,
1948 &reconfig);
1949 /* no change or not supported or no active usecases */
1950 if (ret || !reconfig || !switch_usecases)
1951 return -1;
1952 return 0;
1953#undef VALID_USECASE
1954}
1955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956static int stop_output_stream(struct stream_out *out)
1957{
1958 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 struct audio_usecase *uc_info;
1960 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001961 bool has_voip_usecase =
1962 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963
Eric Laurent994a6932013-07-17 11:51:42 -07001964 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001965 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966 uc_info = get_usecase_from_list(adev, out->usecase);
1967 if (uc_info == NULL) {
1968 ALOGE("%s: Could not find the usecase (%d) in the list",
1969 __func__, out->usecase);
1970 return -EINVAL;
1971 }
1972
Haynes Mathew George41f86652014-06-17 14:22:15 -07001973 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1974 if (adev->visualizer_stop_output != NULL)
1975 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1976 if (adev->offload_effects_stop_output != NULL)
1977 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001978 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1979 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1980 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001981 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001982
Eric Laurent150dbfe2013-02-27 14:31:02 -08001983 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001984 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001985
1986 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001987 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001988
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001989 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
Eric Laurent0499d4f2014-08-25 22:39:29 -05001991 audio_extn_extspk_update(adev->extspk);
1992
Eric Laurent07eeafd2013-10-06 12:52:49 -07001993 /* Must be called after removing the usecase from list */
1994 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1995 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08001996 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001997 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
1998 if (ret == 0) {
1999 /* default service interval was successfully updated,
2000 reopen USB backend with new service interval */
2001 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2002 }
2003 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002004 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002005
HW Lee88512e92018-06-12 15:26:09 +08002006 if (has_voip_usecase ||
2007 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2008 struct listnode *node;
2009 struct audio_usecase *usecase;
2010 list_for_each(node, &adev->usecase_list) {
2011 usecase = node_to_item(node, struct audio_usecase, list);
2012 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2013 continue;
2014
2015 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2016 __func__, usecase->id, use_case_table[usecase->id],
2017 out->usecase, use_case_table[out->usecase]);
2018 select_devices(adev, usecase->id);
2019 }
2020 }
2021
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002022 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002023 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024 return ret;
2025}
2026
2027int start_output_stream(struct stream_out *out)
2028{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 struct audio_usecase *uc_info;
2031 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002032 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Eric Laurent994a6932013-07-17 11:51:42 -07002034 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002035 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002036
2037 if (out->card_status == CARD_STATUS_OFFLINE ||
2038 adev->card_status == CARD_STATUS_OFFLINE) {
2039 ALOGW("out->card_status or adev->card_status offline, try again");
2040 ret = -EAGAIN;
2041 goto error_config;
2042 }
2043
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002044 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2045 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002046 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002047 a2dp_combo = true;
2048 } else {
2049 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2050 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2051 ret = -EAGAIN;
2052 goto error_config;
2053 }
2054 }
2055 }
2056 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002057 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002058 if (out->pcm_device_id < 0) {
2059 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2060 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002061 ret = -EINVAL;
2062 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 }
2064
2065 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2066 uc_info->id = out->usecase;
2067 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002068 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002069 uc_info->devices = out->devices;
2070 uc_info->in_snd_device = SND_DEVICE_NONE;
2071 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072
Eric Laurent07eeafd2013-10-06 12:52:49 -07002073 /* This must be called before adding this usecase to the list */
2074 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2075 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002076 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2077 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2078 /* USB backend is not reopened immediately.
2079 This is eventually done as part of select_devices */
2080 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002081
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002082 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083
Wei Wangf4837d52017-11-21 14:51:20 -08002084 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002085 audio_extn_perf_lock_acquire();
2086
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002087 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2088 (!audio_extn_a2dp_is_ready())) {
2089 if (!a2dp_combo) {
2090 check_a2dp_restore_l(adev, out, false);
2091 } else {
2092 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002093 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2094 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2095 else
2096 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002097 select_devices(adev, out->usecase);
2098 out->devices = dev;
2099 }
2100 } else {
2101 select_devices(adev, out->usecase);
2102 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002103
Eric Laurent0499d4f2014-08-25 22:39:29 -05002104 audio_extn_extspk_update(adev->extspk);
2105
Andy Hung31aca912014-03-20 17:14:59 -07002106 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002107 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002108 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2109 out->pcm = NULL;
2110 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2111 COMPRESS_IN, &out->compr_config);
2112 if (out->compr && !is_compress_ready(out->compr)) {
2113 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2114 compress_close(out->compr);
2115 out->compr = NULL;
2116 ret = -EIO;
2117 goto error_open;
2118 }
2119 if (out->offload_callback)
2120 compress_nonblock(out->compr, out->non_blocking);
2121
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002122 if (adev->visualizer_start_output != NULL) {
2123 int capture_device_id =
2124 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2125 PCM_CAPTURE);
2126 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2127 adev->snd_card, capture_device_id);
2128 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002129 if (adev->offload_effects_start_output != NULL)
2130 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2131 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002132 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002133 ALOGE("%s: pcm stream not ready", __func__);
2134 goto error_open;
2135 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002136 ret = pcm_start(out->pcm);
2137 if (ret < 0) {
2138 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2139 goto error_open;
2140 }
2141 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002142 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002143 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002144
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002145 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2146 flags |= PCM_MMAP | PCM_NOIRQ;
2147 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002148 } else if (out->realtime) {
2149 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002150 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002151
2152 while (1) {
2153 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2154 flags, &out->config);
2155 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2156 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2157 if (out->pcm != NULL) {
2158 pcm_close(out->pcm);
2159 out->pcm = NULL;
2160 }
2161 if (pcm_open_retry_count-- == 0) {
2162 ret = -EIO;
2163 goto error_open;
2164 }
2165 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2166 continue;
2167 }
2168 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002170 ALOGV("%s: pcm_prepare", __func__);
2171 if (pcm_is_ready(out->pcm)) {
2172 ret = pcm_prepare(out->pcm);
2173 if (ret < 0) {
2174 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2175 pcm_close(out->pcm);
2176 out->pcm = NULL;
2177 goto error_open;
2178 }
2179 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002180 if (out->realtime) {
2181 ret = pcm_start(out->pcm);
2182 if (ret < 0) {
2183 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2184 pcm_close(out->pcm);
2185 out->pcm = NULL;
2186 goto error_open;
2187 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002188 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002189 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002190 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002191 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002192 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002193 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002194
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002195 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2196 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2197 audio_low_latency_hint_start();
2198 }
2199
vivek mehtae59cfb22017-06-16 15:57:11 -07002200 // consider a scenario where on pause lower layers are tear down.
2201 // so on resume, swap mixer control need to be sent only when
2202 // backend is active, hence rather than sending from enable device
2203 // sending it from start of streamtream
2204
2205 platform_set_swap_channels(adev, true);
2206
Eric Laurent994a6932013-07-17 11:51:42 -07002207 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002208 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002209error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002210 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002211 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002213error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002214 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215}
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static int check_input_parameters(uint32_t sample_rate,
2218 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002219 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002221 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2222 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002223 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2224 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002225 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2226 return -EINVAL;
2227 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228
Eric Laurent74b55762017-07-09 17:04:53 -07002229 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2230 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002231 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002232 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002233 return -EINVAL;
2234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235
2236 switch (sample_rate) {
2237 case 8000:
2238 case 11025:
2239 case 12000:
2240 case 16000:
2241 case 22050:
2242 case 24000:
2243 case 32000:
2244 case 44100:
2245 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002246 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247 break;
2248 default:
vivek mehtadae44712015-07-27 14:13:18 -07002249 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 return -EINVAL;
2251 }
2252
2253 return 0;
2254}
2255
Kevin Rocarda325aa22018-04-03 09:15:52 -07002256/** Add a value in a list if not already present.
2257 * @return true if value was successfully inserted or already present,
2258 * false if the list is full and does not contain the value.
2259 */
2260static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2261 for (size_t i = 0; i < list_length; i++) {
2262 if (list[i] == value) return true; // value is already present
2263 if (list[i] == 0) { // no values in this slot
2264 list[i] = value;
2265 return true; // value inserted
2266 }
2267 }
2268 return false; // could not insert value
2269}
2270
2271/** Add channel_mask in supported_channel_masks if not already present.
2272 * @return true if channel_mask was successfully inserted or already present,
2273 * false if supported_channel_masks is full and does not contain channel_mask.
2274 */
2275static void register_channel_mask(audio_channel_mask_t channel_mask,
2276 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2277 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2278 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2279}
2280
2281/** Add format in supported_formats if not already present.
2282 * @return true if format was successfully inserted or already present,
2283 * false if supported_formats is full and does not contain format.
2284 */
2285static void register_format(audio_format_t format,
2286 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2287 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2288 "%s: stream can not declare supporting its format %x", __func__, format);
2289}
2290/** Add sample_rate in supported_sample_rates if not already present.
2291 * @return true if sample_rate was successfully inserted or already present,
2292 * false if supported_sample_rates is full and does not contain sample_rate.
2293 */
2294static void register_sample_rate(uint32_t sample_rate,
2295 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2296 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2297 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2298}
2299
vivek mehtaa68fea62017-06-08 19:04:02 -07002300static size_t get_stream_buffer_size(size_t duration_ms,
2301 uint32_t sample_rate,
2302 audio_format_t format,
2303 int channel_count,
2304 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305{
2306 size_t size = 0;
2307
vivek mehtaa68fea62017-06-08 19:04:02 -07002308 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002309 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002310 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002311
2312 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313
Glenn Kasten4f993392014-05-14 07:30:48 -07002314 /* make sure the size is multiple of 32 bytes
2315 * At 48 kHz mono 16-bit PCM:
2316 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2317 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2318 */
2319 size += 0x1f;
2320 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002321
2322 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002323}
2324
2325static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2326{
2327 struct stream_out *out = (struct stream_out *)stream;
2328
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002330}
2331
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002332static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333{
2334 return -ENOSYS;
2335}
2336
2337static size_t out_get_buffer_size(const struct audio_stream *stream)
2338{
2339 struct stream_out *out = (struct stream_out *)stream;
2340
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2342 return out->compr_config.fragment_size;
2343 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002344 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002345 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002346}
2347
2348static uint32_t out_get_channels(const struct audio_stream *stream)
2349{
2350 struct stream_out *out = (struct stream_out *)stream;
2351
2352 return out->channel_mask;
2353}
2354
2355static audio_format_t out_get_format(const struct audio_stream *stream)
2356{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 struct stream_out *out = (struct stream_out *)stream;
2358
2359 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360}
2361
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002362static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
2364 return -ENOSYS;
2365}
2366
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002367/* must be called with out->lock locked */
2368static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 struct stream_out *out = (struct stream_out *)stream;
2371 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002372 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002375 if (adev->adm_deregister_stream)
2376 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002377 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2380 if (out->pcm) {
2381 pcm_close(out->pcm);
2382 out->pcm = NULL;
2383 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002384 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002385 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002386 out->playback_started = false;
2387 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002388 } else {
2389 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002390 out->gapless_mdata.encoder_delay = 0;
2391 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 if (out->compr != NULL) {
2393 compress_close(out->compr);
2394 out->compr = NULL;
2395 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002396 }
Phil Burkbc991042017-02-24 08:06:44 -08002397 if (do_stop) {
2398 stop_output_stream(out);
2399 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002400 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002402 return 0;
2403}
2404
2405static int out_standby(struct audio_stream *stream)
2406{
2407 struct stream_out *out = (struct stream_out *)stream;
2408
2409 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2410 out->usecase, use_case_table[out->usecase]);
2411
2412 lock_output_stream(out);
2413 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002415 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 return 0;
2417}
2418
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002419static int out_on_error(struct audio_stream *stream)
2420{
2421 struct stream_out *out = (struct stream_out *)stream;
2422 struct audio_device *adev = out->dev;
2423 bool do_standby = false;
2424
2425 lock_output_stream(out);
2426 if (!out->standby) {
2427 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2428 stop_compressed_output_l(out);
2429 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2430 } else
2431 do_standby = true;
2432 }
2433 pthread_mutex_unlock(&out->lock);
2434
2435 if (do_standby)
2436 return out_standby(&out->stream.common);
2437
2438 return 0;
2439}
2440
Andy Hung7401c7c2016-09-21 12:41:21 -07002441static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442{
Andy Hung7401c7c2016-09-21 12:41:21 -07002443 struct stream_out *out = (struct stream_out *)stream;
2444
2445 // We try to get the lock for consistency,
2446 // but it isn't necessary for these variables.
2447 // If we're not in standby, we may be blocked on a write.
2448 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2449 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2450 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2451
2452 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002453 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002454 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002455
2456 // dump error info
2457 (void)error_log_dump(
2458 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 return 0;
2461}
2462
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002463static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2464{
2465 int ret = 0;
2466 char value[32];
2467 struct compr_gapless_mdata tmp_mdata;
2468
2469 if (!out || !parms) {
2470 return -EINVAL;
2471 }
2472
2473 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2474 if (ret >= 0) {
2475 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2476 } else {
2477 return -EINVAL;
2478 }
2479
2480 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2481 if (ret >= 0) {
2482 tmp_mdata.encoder_padding = atoi(value);
2483 } else {
2484 return -EINVAL;
2485 }
2486
2487 out->gapless_mdata = tmp_mdata;
2488 out->send_new_metadata = 1;
2489 ALOGV("%s new encoder delay %u and padding %u", __func__,
2490 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2491
2492 return 0;
2493}
2494
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002495static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2496{
2497 return out == adev->primary_output || out == adev->voice_tx_output;
2498}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002499
Kevin Rocard1e02c882017-08-09 15:26:07 -07002500static int get_alive_usb_card(struct str_parms* parms) {
2501 int card;
2502 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2503 !audio_extn_usb_alive(card)) {
2504 return card;
2505 }
2506 return -ENODEV;
2507}
2508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002509static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2510{
2511 struct stream_out *out = (struct stream_out *)stream;
2512 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002513 struct audio_usecase *usecase;
2514 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 struct str_parms *parms;
2516 char value[32];
2517 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002518 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002519 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002520 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521
Eric Laurent2e140aa2016-06-30 17:14:46 -07002522 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002523 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 parms = str_parms_create_str(kvpairs);
2525 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2526 if (ret >= 0) {
2527 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002528
Eric Laurenta1478072015-09-21 17:21:52 -07002529 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002530
2531 // The usb driver needs to be closed after usb device disconnection
2532 // otherwise audio is no longer played on the new usb devices.
2533 // By forcing the stream in standby, the usb stack refcount drops to 0
2534 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002535 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002536 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002537 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2538 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2539 out_standby_l(&out->stream.common);
2540 }
2541 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002542 }
2543
Eric Laurent150dbfe2013-02-27 14:31:02 -08002544 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002546 /*
2547 * When HDMI cable is unplugged the music playback is paused and
2548 * the policy manager sends routing=0. But the audioflinger
2549 * continues to write data until standby time (3sec).
2550 * As the HDMI core is turned off, the write gets blocked.
2551 * Avoid this by routing audio to speaker until standby.
2552 */
2553 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2554 val == AUDIO_DEVICE_NONE) {
2555 val = AUDIO_DEVICE_OUT_SPEAKER;
2556 }
2557
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002558 /*
2559 * When A2DP is disconnected the
2560 * music playback is paused and the policy manager sends routing=0
2561 * But the audioflingercontinues to write data until standby time
2562 * (3sec). As BT is turned off, the write gets blocked.
2563 * Avoid this by routing audio to speaker until standby.
2564 */
2565 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2566 (val == AUDIO_DEVICE_NONE) &&
2567 !audio_extn_a2dp_is_ready()) {
2568 val = AUDIO_DEVICE_OUT_SPEAKER;
2569 }
2570
2571 /* To avoid a2dp to sco overlapping / BT device improper state
2572 * check with BT lib about a2dp streaming support before routing
2573 */
2574 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2575 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002576 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002577 //combo usecase just by pass a2dp
2578 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2579 bypass_a2dp = true;
2580 } else {
2581 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2582 /* update device to a2dp and don't route as BT returned error
2583 * However it is still possible a2dp routing called because
2584 * of current active device disconnection (like wired headset)
2585 */
2586 out->devices = val;
2587 pthread_mutex_unlock(&out->lock);
2588 pthread_mutex_unlock(&adev->lock);
2589 status = -ENOSYS;
2590 goto routing_fail;
2591 }
2592 }
2593 }
2594
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002595 audio_devices_t new_dev = val;
2596
2597 // Workaround: If routing to an non existing usb device, fail gracefully
2598 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002599 int card;
2600 if (audio_is_usb_out_device(new_dev) &&
2601 (card = get_alive_usb_card(parms)) >= 0) {
2602
2603 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002604 pthread_mutex_unlock(&adev->lock);
2605 pthread_mutex_unlock(&out->lock);
2606 status = -ENOSYS;
2607 goto routing_fail;
2608 }
2609
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002610 /*
2611 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002612 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002613 * the select_devices(). But how do we undo this?
2614 *
2615 * For example, music playback is active on headset (deep-buffer usecase)
2616 * and if we go to ringtones and select a ringtone, low-latency usecase
2617 * will be started on headset+speaker. As we can't enable headset+speaker
2618 * and headset devices at the same time, select_devices() switches the music
2619 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2620 * So when the ringtone playback is completed, how do we undo the same?
2621 *
2622 * We are relying on the out_set_parameters() call on deep-buffer output,
2623 * once the ringtone playback is ended.
2624 * NOTE: We should not check if the current devices are same as new devices.
2625 * Because select_devices() must be called to switch back the music
2626 * playback to headset.
2627 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002628 if (new_dev != AUDIO_DEVICE_NONE) {
2629 bool same_dev = out->devices == new_dev;
2630 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002631
Eric Laurenta7657192014-10-09 21:09:33 -07002632 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002633 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002634 if (adev->mode == AUDIO_MODE_IN_CALL) {
2635 adev->current_call_output = out;
2636 ret = voice_start_call(adev);
2637 }
2638 } else {
2639 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002640 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002641 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002642 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002643
2644 if (!out->standby) {
2645 if (!same_dev) {
2646 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002647 // inform adm before actual routing to prevent glitches.
2648 if (adev->adm_on_routing_change) {
2649 adev->adm_on_routing_change(adev->adm_data,
2650 out->handle);
2651 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002652 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002653 if (!bypass_a2dp) {
2654 select_devices(adev, out->usecase);
2655 } else {
juyuchen9baad392018-06-05 19:02:10 +08002656 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2657 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2658 else
2659 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002660 select_devices(adev, out->usecase);
2661 out->devices = new_dev;
2662 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002663 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002664
2665 // on device switch force swap, lower functions will make sure
2666 // to check if swap is allowed or not.
2667
2668 if (!same_dev)
2669 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002670
2671 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2672 out->a2dp_compress_mute &&
2673 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2674 pthread_mutex_lock(&out->compr_mute_lock);
2675 out->a2dp_compress_mute = false;
2676 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2677 pthread_mutex_unlock(&out->compr_mute_lock);
2678 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002679 }
2680
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002681 }
2682
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002684 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002685
2686 /*handles device and call state changes*/
2687 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002688 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002689 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002690
2691 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2692 parse_compress_metadata(out, parms);
2693 }
2694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002695 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002696 ALOGV("%s: exit: code(%d)", __func__, status);
2697 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698}
2699
Haynes Mathew George569b7482017-05-08 14:44:27 -07002700static bool stream_get_parameter_channels(struct str_parms *query,
2701 struct str_parms *reply,
2702 audio_channel_mask_t *supported_channel_masks) {
2703 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002704 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002706 size_t i, j;
2707
2708 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2709 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 value[0] = '\0';
2711 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002712 while (supported_channel_masks[i] != 0) {
2713 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2714 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715 if (!first) {
2716 strcat(value, "|");
2717 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002718 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 first = false;
2720 break;
2721 }
2722 }
2723 i++;
2724 }
2725 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002726 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002727 return ret >= 0;
2728}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002729
Haynes Mathew George569b7482017-05-08 14:44:27 -07002730static bool stream_get_parameter_formats(struct str_parms *query,
2731 struct str_parms *reply,
2732 audio_format_t *supported_formats) {
2733 int ret = -1;
2734 char value[256];
2735 int i;
2736
2737 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2738 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002739 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002740 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002741 case AUDIO_FORMAT_PCM_16_BIT:
2742 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2743 break;
2744 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2745 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2746 break;
2747 case AUDIO_FORMAT_PCM_32_BIT:
2748 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2749 break;
2750 default:
2751 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002752 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002753 break;
2754 }
2755 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002756 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002757 return ret >= 0;
2758}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002759
Haynes Mathew George569b7482017-05-08 14:44:27 -07002760static bool stream_get_parameter_rates(struct str_parms *query,
2761 struct str_parms *reply,
2762 uint32_t *supported_sample_rates) {
2763
2764 int i;
2765 char value[256];
2766 int ret = -1;
2767 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2768 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002769 value[0] = '\0';
2770 i=0;
2771 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002772 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002773 int avail = sizeof(value) - cursor;
2774 ret = snprintf(value + cursor, avail, "%s%d",
2775 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002776 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002777 if (ret < 0 || ret >= avail) {
2778 // if cursor is at the last element of the array
2779 // overwrite with \0 is duplicate work as
2780 // snprintf already put a \0 in place.
2781 // else
2782 // we had space to write the '|' at value[cursor]
2783 // (which will be overwritten) or no space to fill
2784 // the first element (=> cursor == 0)
2785 value[cursor] = '\0';
2786 break;
2787 }
2788 cursor += ret;
2789 ++i;
2790 }
2791 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2792 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002793 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002794 return ret >= 0;
2795}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002796
Haynes Mathew George569b7482017-05-08 14:44:27 -07002797static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2798{
2799 struct stream_out *out = (struct stream_out *)stream;
2800 struct str_parms *query = str_parms_create_str(keys);
2801 char *str;
2802 struct str_parms *reply = str_parms_create();
2803 bool replied = false;
2804 ALOGV("%s: enter: keys - %s", __func__, keys);
2805
2806 replied |= stream_get_parameter_channels(query, reply,
2807 &out->supported_channel_masks[0]);
2808 replied |= stream_get_parameter_formats(query, reply,
2809 &out->supported_formats[0]);
2810 replied |= stream_get_parameter_rates(query, reply,
2811 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002812 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813 str = str_parms_to_str(reply);
2814 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002815 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816 }
2817 str_parms_destroy(query);
2818 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002819 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002820 return str;
2821}
2822
2823static uint32_t out_get_latency(const struct audio_stream_out *stream)
2824{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002825 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002827 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2830 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002831 else if ((out->realtime) ||
2832 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002833 // since the buffer won't be filled up faster than realtime,
2834 // return a smaller number
2835 period_ms = (out->af_period_multiplier * out->config.period_size *
2836 1000) / (out->config.rate);
2837 hw_delay = platform_render_latency(out->usecase)/1000;
2838 return period_ms + hw_delay;
2839 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002840
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002841 latency = (out->config.period_count * out->config.period_size * 1000) /
2842 (out->config.rate);
2843
2844 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2845 latency += audio_extn_a2dp_get_encoder_latency();
2846
2847 return latency;
2848}
2849
2850static int set_compr_volume(struct audio_stream_out *stream, float left,
2851 float right)
2852{
2853 struct stream_out *out = (struct stream_out *)stream;
2854 int volume[2];
2855 char mixer_ctl_name[128];
2856 struct audio_device *adev = out->dev;
2857 struct mixer_ctl *ctl;
2858 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2859 PCM_PLAYBACK);
2860
2861 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2862 "Compress Playback %d Volume", pcm_device_id);
2863 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2864 if (!ctl) {
2865 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2866 __func__, mixer_ctl_name);
2867 return -EINVAL;
2868 }
2869 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2870 __func__, mixer_ctl_name, left, right);
2871 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2872 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2873 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2874
2875 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876}
2877
2878static int out_set_volume(struct audio_stream_out *stream, float left,
2879 float right)
2880{
Eric Laurenta9024de2013-04-04 09:19:12 -07002881 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002882 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002884 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002885 /* only take left channel into account: the API is for stereo anyway */
2886 out->muted = (left == 0.0f);
2887 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002889 pthread_mutex_lock(&out->compr_mute_lock);
2890 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2891 if (!out->a2dp_compress_mute)
2892 ret = set_compr_volume(stream, left, right);
2893 out->volume_l = left;
2894 out->volume_r = right;
2895 pthread_mutex_unlock(&out->compr_mute_lock);
2896 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002897 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002898 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2899 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2900 if (!out->standby) {
2901 // if in standby, cached volume will be sent after stream is opened
2902 audio_extn_utils_send_app_type_gain(out->dev,
2903 out->app_type_cfg.app_type,
2904 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002905 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002906 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002907 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909 return -ENOSYS;
2910}
2911
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002912// note: this call is safe only if the stream_cb is
2913// removed first in close_output_stream (as is done now).
2914static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2915{
2916 if (!stream || !parms)
2917 return;
2918
2919 struct stream_out *out = (struct stream_out *)stream;
2920 struct audio_device *adev = out->dev;
2921
2922 card_status_t status;
2923 int card;
2924 if (parse_snd_card_status(parms, &card, &status) < 0)
2925 return;
2926
2927 pthread_mutex_lock(&adev->lock);
2928 bool valid_cb = (card == adev->snd_card);
2929 pthread_mutex_unlock(&adev->lock);
2930
2931 if (!valid_cb)
2932 return;
2933
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002934 lock_output_stream(out);
2935 if (out->card_status != status)
2936 out->card_status = status;
2937 pthread_mutex_unlock(&out->lock);
2938
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002939 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2940 use_case_table[out->usecase],
2941 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2942
2943 if (status == CARD_STATUS_OFFLINE)
2944 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002945
2946 return;
2947}
2948
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002949#ifdef NO_AUDIO_OUT
2950static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002951 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002952{
2953 struct stream_out *out = (struct stream_out *)stream;
2954
2955 /* No Output device supported other than BT for playback.
2956 * Sleep for the amount of buffer duration
2957 */
Eric Laurenta1478072015-09-21 17:21:52 -07002958 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002959 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2960 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002961 out_get_sample_rate(&out->stream.common));
2962 pthread_mutex_unlock(&out->lock);
2963 return bytes;
2964}
2965#endif
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2968 size_t bytes)
2969{
2970 struct stream_out *out = (struct stream_out *)stream;
2971 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002972 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002973 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974
Eric Laurenta1478072015-09-21 17:21:52 -07002975 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002976 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002977 const size_t frame_size = audio_stream_out_frame_size(stream);
2978 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002979
Eric Laurent0e46adf2016-12-16 12:49:24 -08002980 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2981 error_code = ERROR_CODE_WRITE;
2982 goto exit;
2983 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002984
2985 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2986 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08002987 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002988 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2989 ret = -EIO;
2990 goto exit;
2991 }
2992 }
2993 }
2994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002996 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002997 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003000 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003002 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003003 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004 goto exit;
3005 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003006
vivek mehta40125092017-08-21 18:48:51 -07003007 // after standby always force set last known cal step
3008 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3009 ALOGD("%s: retry previous failed cal level set", __func__);
3010 send_gain_dep_calibration_l();
3011 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003014 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003015 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003016 if (out->send_new_metadata) {
3017 ALOGVV("send new gapless metadata");
3018 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3019 out->send_new_metadata = 0;
3020 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003021 unsigned int avail;
3022 struct timespec tstamp;
3023 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3024 /* Do not limit write size if the available frames count is unknown */
3025 if (ret != 0) {
3026 avail = bytes;
3027 }
3028 if (avail == 0) {
3029 ret = 0;
3030 } else {
3031 if (avail > bytes) {
3032 avail = bytes;
3033 }
3034 ret = compress_write(out->compr, buffer, avail);
3035 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3036 __func__, avail, ret);
3037 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003038
Eric Laurent6e895242013-09-05 16:10:57 -07003039 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3041 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003042 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003043 compress_start(out->compr);
3044 out->playback_started = 1;
3045 out->offload_state = OFFLOAD_STATE_PLAYING;
3046 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003047 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003048 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003049 } else {
3050 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003051 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003052 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003053 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 return ret;
3055 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003056 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003058 size_t bytes_to_write = bytes;
3059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003060 if (out->muted)
3061 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003062 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003063 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003064 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3065 int16_t *src = (int16_t *)buffer;
3066 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003067
Eric Laurentad2dde92017-09-20 18:27:31 -07003068 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3069 out->format != AUDIO_FORMAT_PCM_16_BIT,
3070 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003071
Eric Laurentad2dde92017-09-20 18:27:31 -07003072 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3073 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3074 }
3075 bytes_to_write /= 2;
3076 }
3077 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3078
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003079 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003080 request_out_focus(out, ns);
3081
3082 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3083 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003084 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003085 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003086 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003087
Haynes Mathew George03c40102016-01-29 17:57:48 -08003088 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003089 } else {
3090 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 }
3093
3094exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003095 // For PCM we always consume the buffer and return #bytes regardless of ret.
3096 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003097 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003098 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003099 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003100
Andy Hung7401c7c2016-09-21 12:41:21 -07003101 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003102 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003103 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3104 ALOGE_IF(out->pcm != NULL,
3105 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003106 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003107 // usleep not guaranteed for values over 1 second but we don't limit here.
3108 }
3109 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 pthread_mutex_unlock(&out->lock);
3112
3113 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003114 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003115 if (sleeptime_us != 0)
3116 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 }
3118 return bytes;
3119}
3120
3121static int out_get_render_position(const struct audio_stream_out *stream,
3122 uint32_t *dsp_frames)
3123{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003124 struct stream_out *out = (struct stream_out *)stream;
3125 *dsp_frames = 0;
3126 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003127 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003128 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003129 unsigned long frames = 0;
3130 // TODO: check return value
3131 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3132 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133 ALOGVV("%s rendered frames %d sample_rate %d",
3134 __func__, *dsp_frames, out->sample_rate);
3135 }
3136 pthread_mutex_unlock(&out->lock);
3137 return 0;
3138 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003139 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140}
3141
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003142static int out_add_audio_effect(const struct audio_stream *stream __unused,
3143 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144{
3145 return 0;
3146}
3147
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003148static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3149 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150{
3151 return 0;
3152}
3153
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003154static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3155 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003157 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158}
3159
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003160static int out_get_presentation_position(const struct audio_stream_out *stream,
3161 uint64_t *frames, struct timespec *timestamp)
3162{
3163 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003164 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003165 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003166
Eric Laurenta1478072015-09-21 17:21:52 -07003167 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003168
Eric Laurent949a0892013-09-20 09:20:13 -07003169 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3170 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003171 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003172 compress_get_tstamp(out->compr, &dsp_frames,
3173 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003174 // Adjustment accounts for A2DP encoder latency with offload usecases
3175 // Note: Encoder latency is returned in ms.
3176 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3177 unsigned long offset =
3178 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3179 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3180 }
Eric Laurent949a0892013-09-20 09:20:13 -07003181 ALOGVV("%s rendered frames %ld sample_rate %d",
3182 __func__, dsp_frames, out->sample_rate);
3183 *frames = dsp_frames;
3184 ret = 0;
3185 /* this is the best we can do */
3186 clock_gettime(CLOCK_MONOTONIC, timestamp);
3187 }
3188 } else {
3189 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003190 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003191 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3192 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003193 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003194 // This adjustment accounts for buffering after app processor.
3195 // It is based on estimated DSP latency per use case, rather than exact.
3196 signed_frames -=
3197 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3198
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003199 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3200 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3201 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3202 signed_frames -=
3203 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3204 }
3205
Eric Laurent949a0892013-09-20 09:20:13 -07003206 // It would be unusual for this value to be negative, but check just in case ...
3207 if (signed_frames >= 0) {
3208 *frames = signed_frames;
3209 ret = 0;
3210 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003211 }
3212 }
3213 }
3214
3215 pthread_mutex_unlock(&out->lock);
3216
3217 return ret;
3218}
3219
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220static int out_set_callback(struct audio_stream_out *stream,
3221 stream_callback_t callback, void *cookie)
3222{
3223 struct stream_out *out = (struct stream_out *)stream;
3224
3225 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003226 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003227 out->offload_callback = callback;
3228 out->offload_cookie = cookie;
3229 pthread_mutex_unlock(&out->lock);
3230 return 0;
3231}
3232
3233static int out_pause(struct audio_stream_out* stream)
3234{
3235 struct stream_out *out = (struct stream_out *)stream;
3236 int status = -ENOSYS;
3237 ALOGV("%s", __func__);
3238 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003239 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3241 status = compress_pause(out->compr);
3242 out->offload_state = OFFLOAD_STATE_PAUSED;
3243 }
3244 pthread_mutex_unlock(&out->lock);
3245 }
3246 return status;
3247}
3248
3249static int out_resume(struct audio_stream_out* stream)
3250{
3251 struct stream_out *out = (struct stream_out *)stream;
3252 int status = -ENOSYS;
3253 ALOGV("%s", __func__);
3254 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3255 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003256 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003257 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3258 status = compress_resume(out->compr);
3259 out->offload_state = OFFLOAD_STATE_PLAYING;
3260 }
3261 pthread_mutex_unlock(&out->lock);
3262 }
3263 return status;
3264}
3265
3266static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3267{
3268 struct stream_out *out = (struct stream_out *)stream;
3269 int status = -ENOSYS;
3270 ALOGV("%s", __func__);
3271 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003272 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3274 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3275 else
3276 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3277 pthread_mutex_unlock(&out->lock);
3278 }
3279 return status;
3280}
3281
3282static int out_flush(struct audio_stream_out* stream)
3283{
3284 struct stream_out *out = (struct stream_out *)stream;
3285 ALOGV("%s", __func__);
3286 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003287 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 stop_compressed_output_l(out);
3289 pthread_mutex_unlock(&out->lock);
3290 return 0;
3291 }
3292 return -ENOSYS;
3293}
3294
Eric Laurent0e46adf2016-12-16 12:49:24 -08003295static int out_stop(const struct audio_stream_out* stream)
3296{
3297 struct stream_out *out = (struct stream_out *)stream;
3298 struct audio_device *adev = out->dev;
3299 int ret = -ENOSYS;
3300
3301 ALOGV("%s", __func__);
3302 pthread_mutex_lock(&adev->lock);
3303 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3304 out->playback_started && out->pcm != NULL) {
3305 pcm_stop(out->pcm);
3306 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003307 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003308 }
3309 pthread_mutex_unlock(&adev->lock);
3310 return ret;
3311}
3312
3313static int out_start(const struct audio_stream_out* stream)
3314{
3315 struct stream_out *out = (struct stream_out *)stream;
3316 struct audio_device *adev = out->dev;
3317 int ret = -ENOSYS;
3318
3319 ALOGV("%s", __func__);
3320 pthread_mutex_lock(&adev->lock);
3321 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3322 !out->playback_started && out->pcm != NULL) {
3323 ret = start_output_stream(out);
3324 if (ret == 0) {
3325 out->playback_started = true;
3326 }
3327 }
3328 pthread_mutex_unlock(&adev->lock);
3329 return ret;
3330}
3331
Phil Burkbc991042017-02-24 08:06:44 -08003332/*
3333 * Modify config->period_count based on min_size_frames
3334 */
3335static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3336{
3337 int periodCountRequested = (min_size_frames + config->period_size - 1)
3338 / config->period_size;
3339 int periodCount = MMAP_PERIOD_COUNT_MIN;
3340
3341 ALOGV("%s original config.period_size = %d config.period_count = %d",
3342 __func__, config->period_size, config->period_count);
3343
3344 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3345 periodCount *= 2;
3346 }
3347 config->period_count = periodCount;
3348
3349 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3350}
3351
Eric Laurent0e46adf2016-12-16 12:49:24 -08003352static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3353 int32_t min_size_frames,
3354 struct audio_mmap_buffer_info *info)
3355{
3356 struct stream_out *out = (struct stream_out *)stream;
3357 struct audio_device *adev = out->dev;
3358 int ret = 0;
3359 unsigned int offset1;
3360 unsigned int frames1;
3361 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003362 uint32_t mmap_size;
3363 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003364
3365 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003366 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003367 pthread_mutex_lock(&adev->lock);
3368
3369 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003370 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003371 ret = -EINVAL;
3372 goto exit;
3373 }
3374 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003375 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003376 ret = -ENOSYS;
3377 goto exit;
3378 }
3379 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3380 if (out->pcm_device_id < 0) {
3381 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3382 __func__, out->pcm_device_id, out->usecase);
3383 ret = -EINVAL;
3384 goto exit;
3385 }
Phil Burkbc991042017-02-24 08:06:44 -08003386
3387 adjust_mmap_period_count(&out->config, min_size_frames);
3388
Eric Laurent0e46adf2016-12-16 12:49:24 -08003389 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3390 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3391 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3392 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3393 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3394 step = "open";
3395 ret = -ENODEV;
3396 goto exit;
3397 }
3398 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3399 if (ret < 0) {
3400 step = "begin";
3401 goto exit;
3402 }
3403 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003404 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003405 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003406 ret = platform_get_mmap_data_fd(adev->platform,
3407 out->pcm_device_id, 0 /*playback*/,
3408 &info->shared_memory_fd,
3409 &mmap_size);
3410 if (ret < 0) {
3411 // Fall back to non exclusive mode
3412 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3413 } else {
3414 if (mmap_size < buffer_size) {
3415 step = "mmap";
3416 goto exit;
3417 }
3418 // FIXME: indicate exclusive mode support by returning a negative buffer size
3419 info->buffer_size_frames *= -1;
3420 }
3421 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003422
3423 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3424 if (ret < 0) {
3425 step = "commit";
3426 goto exit;
3427 }
Phil Burkbc991042017-02-24 08:06:44 -08003428
3429 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003430 ret = 0;
3431
3432 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3433 __func__, info->shared_memory_address, info->buffer_size_frames);
3434
3435exit:
3436 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003437 if (out->pcm == NULL) {
3438 ALOGE("%s: %s - %d", __func__, step, ret);
3439 } else {
3440 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003441 pcm_close(out->pcm);
3442 out->pcm = NULL;
3443 }
3444 }
3445 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003446 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003447 return ret;
3448}
3449
3450static int out_get_mmap_position(const struct audio_stream_out *stream,
3451 struct audio_mmap_position *position)
3452{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003453 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454 struct stream_out *out = (struct stream_out *)stream;
3455 ALOGVV("%s", __func__);
3456 if (position == NULL) {
3457 return -EINVAL;
3458 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003459 lock_output_stream(out);
3460 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3461 out->pcm == NULL) {
3462 ret = -ENOSYS;
3463 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003464 }
3465
3466 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003467 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003468 if (ret < 0) {
3469 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003470 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003471 }
Andy Hungfc044e12017-03-20 09:24:22 -07003472 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003473exit:
3474 pthread_mutex_unlock(&out->lock);
3475 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003476}
3477
3478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479/** audio_stream_in implementation **/
3480static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3481{
3482 struct stream_in *in = (struct stream_in *)stream;
3483
3484 return in->config.rate;
3485}
3486
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003487static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488{
3489 return -ENOSYS;
3490}
3491
3492static size_t in_get_buffer_size(const struct audio_stream *stream)
3493{
3494 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003495 return in->config.period_size * in->af_period_multiplier *
3496 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003497}
3498
3499static uint32_t in_get_channels(const struct audio_stream *stream)
3500{
3501 struct stream_in *in = (struct stream_in *)stream;
3502
3503 return in->channel_mask;
3504}
3505
vivek mehta4ed66e62016-04-15 23:33:34 -07003506static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507{
vivek mehta4ed66e62016-04-15 23:33:34 -07003508 struct stream_in *in = (struct stream_in *)stream;
3509 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510}
3511
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003512static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513{
3514 return -ENOSYS;
3515}
3516
3517static int in_standby(struct audio_stream *stream)
3518{
3519 struct stream_in *in = (struct stream_in *)stream;
3520 struct audio_device *adev = in->dev;
3521 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003522 bool do_stop = true;
3523
Eric Laurent994a6932013-07-17 11:51:42 -07003524 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003525
3526 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003527
3528 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003529 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003530 audio_extn_sound_trigger_stop_lab(in);
3531 in->standby = true;
3532 }
3533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003534 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003535 if (adev->adm_deregister_stream)
3536 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3537
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003538 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003540 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003541 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003542 in->capture_started = false;
3543 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003544 if (in->pcm) {
3545 pcm_close(in->pcm);
3546 in->pcm = NULL;
3547 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003548 adev->enable_voicerx = false;
3549 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003550 if (do_stop) {
3551 status = stop_input_stream(in);
3552 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003553 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554 }
3555 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003556 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 return status;
3558}
3559
Andy Hungd13f0d32017-06-12 13:58:37 -07003560static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561{
Andy Hungd13f0d32017-06-12 13:58:37 -07003562 struct stream_in *in = (struct stream_in *)stream;
3563
3564 // We try to get the lock for consistency,
3565 // but it isn't necessary for these variables.
3566 // If we're not in standby, we may be blocked on a read.
3567 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3568 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3569 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3570 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3571
3572 if (locked) {
3573 pthread_mutex_unlock(&in->lock);
3574 }
3575
3576 // dump error info
3577 (void)error_log_dump(
3578 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 return 0;
3580}
3581
3582static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3583{
3584 struct stream_in *in = (struct stream_in *)stream;
3585 struct audio_device *adev = in->dev;
3586 struct str_parms *parms;
3587 char *str;
3588 char value[32];
3589 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003590 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591
Eric Laurent994a6932013-07-17 11:51:42 -07003592 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 parms = str_parms_create_str(kvpairs);
3594
3595 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3596
Eric Laurenta1478072015-09-21 17:21:52 -07003597 lock_input_stream(in);
3598
Eric Laurent150dbfe2013-02-27 14:31:02 -08003599 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 if (ret >= 0) {
3601 val = atoi(value);
3602 /* no audio source uses val == 0 */
3603 if ((in->source != val) && (val != 0)) {
3604 in->source = val;
3605 }
3606 }
3607
3608 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 if (ret >= 0) {
3611 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003612 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003613
3614 // Workaround: If routing to an non existing usb device, fail gracefully
3615 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003616 int card;
3617 if (audio_is_usb_in_device(val) &&
3618 (card = get_alive_usb_card(parms)) >= 0) {
3619
3620 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003621 status = -ENOSYS;
3622 } else {
3623
3624 in->device = val;
3625 /* If recording is in progress, change the tx device to new device */
3626 if (!in->standby) {
3627 ALOGV("update input routing change");
3628 // inform adm before actual routing to prevent glitches.
3629 if (adev->adm_on_routing_change) {
3630 adev->adm_on_routing_change(adev->adm_data,
3631 in->capture_handle);
3632 }
3633 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003634 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003635 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 }
3637 }
3638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003640 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641
3642 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003643 ALOGV("%s: exit: status(%d)", __func__, status);
3644 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645}
3646
Haynes Mathew George569b7482017-05-08 14:44:27 -07003647static char* in_get_parameters(const struct audio_stream *stream,
3648 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003649{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003650 struct stream_in *in = (struct stream_in *)stream;
3651 struct str_parms *query = str_parms_create_str(keys);
3652 char *str;
3653 struct str_parms *reply = str_parms_create();
3654 bool replied = false;
3655
3656 ALOGV("%s: enter: keys - %s", __func__, keys);
3657 replied |= stream_get_parameter_channels(query, reply,
3658 &in->supported_channel_masks[0]);
3659 replied |= stream_get_parameter_formats(query, reply,
3660 &in->supported_formats[0]);
3661 replied |= stream_get_parameter_rates(query, reply,
3662 &in->supported_sample_rates[0]);
3663 if (replied) {
3664 str = str_parms_to_str(reply);
3665 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003666 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003667 }
3668 str_parms_destroy(query);
3669 str_parms_destroy(reply);
3670 ALOGV("%s: exit: returns - %s", __func__, str);
3671 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672}
3673
Eric Laurent51f3c662018-04-10 18:21:34 -07003674static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675{
Eric Laurent51f3c662018-04-10 18:21:34 -07003676 struct stream_in *in = (struct stream_in *)stream;
3677 char mixer_ctl_name[128];
3678 struct mixer_ctl *ctl;
3679 int ctl_value;
3680
3681 ALOGV("%s: gain %f", __func__, gain);
3682
3683 if (stream == NULL)
3684 return -EINVAL;
3685
3686 /* in_set_gain() only used to silence MMAP capture for now */
3687 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3688 return -ENOSYS;
3689
3690 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3691
3692 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3693 if (!ctl) {
3694 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3695 __func__, mixer_ctl_name);
3696 return -ENOSYS;
3697 }
3698
3699 if (gain < RECORD_GAIN_MIN)
3700 gain = RECORD_GAIN_MIN;
3701 else if (gain > RECORD_GAIN_MAX)
3702 gain = RECORD_GAIN_MAX;
3703 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3704
3705 mixer_ctl_set_value(ctl, 0, ctl_value);
3706 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707}
3708
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003709static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3710{
3711 if (!stream || !parms)
3712 return;
3713
3714 struct stream_in *in = (struct stream_in *)stream;
3715 struct audio_device *adev = in->dev;
3716
3717 card_status_t status;
3718 int card;
3719 if (parse_snd_card_status(parms, &card, &status) < 0)
3720 return;
3721
3722 pthread_mutex_lock(&adev->lock);
3723 bool valid_cb = (card == adev->snd_card);
3724 pthread_mutex_unlock(&adev->lock);
3725
3726 if (!valid_cb)
3727 return;
3728
3729 lock_input_stream(in);
3730 if (in->card_status != status)
3731 in->card_status = status;
3732 pthread_mutex_unlock(&in->lock);
3733
3734 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3735 use_case_table[in->usecase],
3736 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3737
3738 // a better solution would be to report error back to AF and let
3739 // it put the stream to standby
3740 if (status == CARD_STATUS_OFFLINE)
3741 in_standby(&in->stream.common);
3742
3743 return;
3744}
3745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3747 size_t bytes)
3748{
3749 struct stream_in *in = (struct stream_in *)stream;
3750 struct audio_device *adev = in->dev;
3751 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003752 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003753 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754
Eric Laurenta1478072015-09-21 17:21:52 -07003755 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003756 const size_t frame_size = audio_stream_in_frame_size(stream);
3757 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003758
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003759 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003760 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003761 /* Read from sound trigger HAL */
3762 audio_extn_sound_trigger_read(in, buffer, bytes);
3763 pthread_mutex_unlock(&in->lock);
3764 return bytes;
3765 }
3766
Eric Laurent0e46adf2016-12-16 12:49:24 -08003767 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3768 ret = -ENOSYS;
3769 goto exit;
3770 }
3771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003773 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003775 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 goto exit;
3778 }
3779 in->standby = 0;
3780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781
Andy Hungd13f0d32017-06-12 13:58:37 -07003782 // errors that occur here are read errors.
3783 error_code = ERROR_CODE_READ;
3784
Haynes Mathew George03c40102016-01-29 17:57:48 -08003785 //what's the duration requested by the client?
3786 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3787 in->config.rate;
3788 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003789
Haynes Mathew George03c40102016-01-29 17:57:48 -08003790 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003792 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003793 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003794 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003795 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003796 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003797 if (ret < 0) {
3798 ALOGE("Failed to read w/err %s", strerror(errno));
3799 ret = -errno;
3800 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003801 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3802 if (bytes % 4 == 0) {
3803 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3804 int_buf_stream = buffer;
3805 for (size_t itt=0; itt < bytes/4 ; itt++) {
3806 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003807 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003808 } else {
3809 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3810 ret = -EINVAL;
3811 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003812 }
3813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 }
3815
Haynes Mathew George03c40102016-01-29 17:57:48 -08003816 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 /*
3819 * Instead of writing zeroes here, we could trust the hardware
3820 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003821 * 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 -08003822 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003823 if (ret == 0 && adev->mic_muted &&
3824 !voice_is_in_call_rec_stream(in) &&
3825 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003827 in->frames_muted += frames;
3828 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829
3830exit:
3831 pthread_mutex_unlock(&in->lock);
3832
3833 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003834 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 in_standby(&in->stream.common);
3836 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003837 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003838 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003839 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003840 }
3841 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003842 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 }
3844 return bytes;
3845}
3846
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003847static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848{
3849 return 0;
3850}
3851
Andy Hung6ebe5962016-01-15 17:46:57 -08003852static int in_get_capture_position(const struct audio_stream_in *stream,
3853 int64_t *frames, int64_t *time)
3854{
3855 if (stream == NULL || frames == NULL || time == NULL) {
3856 return -EINVAL;
3857 }
3858 struct stream_in *in = (struct stream_in *)stream;
3859 int ret = -ENOSYS;
3860
3861 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003862 // note: ST sessions do not close the alsa pcm driver synchronously
3863 // on standby. Therefore, we may return an error even though the
3864 // pcm stream is still opened.
3865 if (in->standby) {
3866 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3867 "%s stream in standby but pcm not NULL for non ST session", __func__);
3868 goto exit;
3869 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003870 if (in->pcm) {
3871 struct timespec timestamp;
3872 unsigned int avail;
3873 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3874 *frames = in->frames_read + avail;
3875 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3876 ret = 0;
3877 }
3878 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003879exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003880 pthread_mutex_unlock(&in->lock);
3881 return ret;
3882}
3883
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003884static int add_remove_audio_effect(const struct audio_stream *stream,
3885 effect_handle_t effect,
3886 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003888 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003889 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003890 int status = 0;
3891 effect_descriptor_t desc;
3892
3893 status = (*effect)->get_descriptor(effect, &desc);
3894 if (status != 0)
3895 return status;
3896
Eric Laurenta1478072015-09-21 17:21:52 -07003897 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003898 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003899 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003900 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003901 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003902 in->enable_aec != enable &&
3903 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3904 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003905 if (!enable)
3906 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003907 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3908 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3909 adev->enable_voicerx = enable;
3910 struct audio_usecase *usecase;
3911 struct listnode *node;
3912 list_for_each(node, &adev->usecase_list) {
3913 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003914 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003915 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003916 }
3917 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003918 if (!in->standby)
3919 select_devices(in->dev, in->usecase);
3920 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003921 if (in->enable_ns != enable &&
3922 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3923 in->enable_ns = enable;
3924 if (!in->standby)
3925 select_devices(in->dev, in->usecase);
3926 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003927 pthread_mutex_unlock(&in->dev->lock);
3928 pthread_mutex_unlock(&in->lock);
3929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 return 0;
3931}
3932
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003933static int in_add_audio_effect(const struct audio_stream *stream,
3934 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935{
Eric Laurent994a6932013-07-17 11:51:42 -07003936 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003937 return add_remove_audio_effect(stream, effect, true);
3938}
3939
3940static int in_remove_audio_effect(const struct audio_stream *stream,
3941 effect_handle_t effect)
3942{
Eric Laurent994a6932013-07-17 11:51:42 -07003943 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003944 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945}
3946
Eric Laurent0e46adf2016-12-16 12:49:24 -08003947static int in_stop(const struct audio_stream_in* stream)
3948{
3949 struct stream_in *in = (struct stream_in *)stream;
3950 struct audio_device *adev = in->dev;
3951
3952 int ret = -ENOSYS;
3953 ALOGV("%s", __func__);
3954 pthread_mutex_lock(&adev->lock);
3955 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3956 in->capture_started && in->pcm != NULL) {
3957 pcm_stop(in->pcm);
3958 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003959 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003960 }
3961 pthread_mutex_unlock(&adev->lock);
3962 return ret;
3963}
3964
3965static int in_start(const struct audio_stream_in* stream)
3966{
3967 struct stream_in *in = (struct stream_in *)stream;
3968 struct audio_device *adev = in->dev;
3969 int ret = -ENOSYS;
3970
3971 ALOGV("%s in %p", __func__, in);
3972 pthread_mutex_lock(&adev->lock);
3973 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3974 !in->capture_started && in->pcm != NULL) {
3975 if (!in->capture_started) {
3976 ret = start_input_stream(in);
3977 if (ret == 0) {
3978 in->capture_started = true;
3979 }
3980 }
3981 }
3982 pthread_mutex_unlock(&adev->lock);
3983 return ret;
3984}
3985
3986static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3987 int32_t min_size_frames,
3988 struct audio_mmap_buffer_info *info)
3989{
3990 struct stream_in *in = (struct stream_in *)stream;
3991 struct audio_device *adev = in->dev;
3992 int ret = 0;
3993 unsigned int offset1;
3994 unsigned int frames1;
3995 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003996 uint32_t mmap_size;
3997 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003998
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003999 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004000 pthread_mutex_lock(&adev->lock);
4001 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004002
Eric Laurent0e46adf2016-12-16 12:49:24 -08004003 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004004 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004005 ret = -EINVAL;
4006 goto exit;
4007 }
4008 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004009 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004010 ALOGV("%s in %p", __func__, in);
4011 ret = -ENOSYS;
4012 goto exit;
4013 }
4014 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4015 if (in->pcm_device_id < 0) {
4016 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4017 __func__, in->pcm_device_id, in->usecase);
4018 ret = -EINVAL;
4019 goto exit;
4020 }
Phil Burkbc991042017-02-24 08:06:44 -08004021
4022 adjust_mmap_period_count(&in->config, min_size_frames);
4023
Eric Laurent0e46adf2016-12-16 12:49:24 -08004024 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4025 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4026 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4027 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4028 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4029 step = "open";
4030 ret = -ENODEV;
4031 goto exit;
4032 }
4033
4034 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4035 if (ret < 0) {
4036 step = "begin";
4037 goto exit;
4038 }
4039 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004040 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004041 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004042 ret = platform_get_mmap_data_fd(adev->platform,
4043 in->pcm_device_id, 1 /*capture*/,
4044 &info->shared_memory_fd,
4045 &mmap_size);
4046 if (ret < 0) {
4047 // Fall back to non exclusive mode
4048 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4049 } else {
4050 if (mmap_size < buffer_size) {
4051 step = "mmap";
4052 goto exit;
4053 }
4054 // FIXME: indicate exclusive mode support by returning a negative buffer size
4055 info->buffer_size_frames *= -1;
4056 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004057
Haynes Mathew George96483a22017-03-28 14:52:47 -07004058 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004059
4060 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4061 if (ret < 0) {
4062 step = "commit";
4063 goto exit;
4064 }
4065
Phil Burkbc991042017-02-24 08:06:44 -08004066 in->standby = false;
4067 ret = 0;
4068
Eric Laurent0e46adf2016-12-16 12:49:24 -08004069 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4070 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004071
4072exit:
4073 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004074 if (in->pcm == NULL) {
4075 ALOGE("%s: %s - %d", __func__, step, ret);
4076 } else {
4077 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004078 pcm_close(in->pcm);
4079 in->pcm = NULL;
4080 }
4081 }
4082 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004083 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004084 return ret;
4085}
4086
4087static int in_get_mmap_position(const struct audio_stream_in *stream,
4088 struct audio_mmap_position *position)
4089{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004090 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004091 struct stream_in *in = (struct stream_in *)stream;
4092 ALOGVV("%s", __func__);
4093 if (position == NULL) {
4094 return -EINVAL;
4095 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004096 lock_input_stream(in);
4097 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4098 in->pcm == NULL) {
4099 ret = -ENOSYS;
4100 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004101 }
4102 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004103 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004104 if (ret < 0) {
4105 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004106 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004107 }
Andy Hungfc044e12017-03-20 09:24:22 -07004108 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004109exit:
4110 pthread_mutex_unlock(&in->lock);
4111 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004112}
4113
jiabin8962a4d2018-03-19 18:21:24 -07004114static int in_get_active_microphones(const struct audio_stream_in *stream,
4115 struct audio_microphone_characteristic_t *mic_array,
4116 size_t *mic_count) {
4117 struct stream_in *in = (struct stream_in *)stream;
4118 struct audio_device *adev = in->dev;
4119 ALOGVV("%s", __func__);
4120
4121 lock_input_stream(in);
4122 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004123 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004124 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004125 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004126 pthread_mutex_unlock(&adev->lock);
4127 pthread_mutex_unlock(&in->lock);
4128
4129 return ret;
4130}
4131
4132static int adev_get_microphones(const struct audio_hw_device *dev,
4133 struct audio_microphone_characteristic_t *mic_array,
4134 size_t *mic_count) {
4135 struct audio_device *adev = (struct audio_device *)dev;
4136 ALOGVV("%s", __func__);
4137
4138 pthread_mutex_lock(&adev->lock);
4139 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4140 pthread_mutex_unlock(&adev->lock);
4141
4142 return ret;
4143}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145static int adev_open_output_stream(struct audio_hw_device *dev,
4146 audio_io_handle_t handle,
4147 audio_devices_t devices,
4148 audio_output_flags_t flags,
4149 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004150 struct audio_stream_out **stream_out,
4151 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152{
4153 struct audio_device *adev = (struct audio_device *)dev;
4154 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004155 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004156 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4157 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4158 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159
Andy Hungd9653bd2017-08-01 19:31:39 -07004160 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4161 return -ENOSYS;
4162 }
4163
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004164 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4165 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 *stream_out = NULL;
4167 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4168
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004169 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 if (devices == AUDIO_DEVICE_NONE)
4172 devices = AUDIO_DEVICE_OUT_SPEAKER;
4173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174 out->flags = flags;
4175 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004176 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004177 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004178 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179
4180 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004181 if ((is_hdmi || is_usb_dev) &&
4182 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4183 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4184 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004185 audio_format_t req_format = config->format;
4186 audio_channel_mask_t req_channel_mask = config->channel_mask;
4187 uint32_t req_sample_rate = config->sample_rate;
4188
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004189 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004190 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004191 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004192 if (config->sample_rate == 0)
4193 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004194 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004195 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4196 if (config->format == AUDIO_FORMAT_DEFAULT)
4197 config->format = AUDIO_FORMAT_PCM_16_BIT;
4198 } else if (is_usb_dev) {
4199 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4200 &config->format,
4201 &out->supported_formats[0],
4202 MAX_SUPPORTED_FORMATS,
4203 &config->channel_mask,
4204 &out->supported_channel_masks[0],
4205 MAX_SUPPORTED_CHANNEL_MASKS,
4206 &config->sample_rate,
4207 &out->supported_sample_rates[0],
4208 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004209 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004210 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004211 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004212 if (ret != 0) {
4213 // For MMAP NO IRQ, allow conversions in ADSP
4214 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4215 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004216
Eric Laurentab805ee2018-03-30 12:20:38 -07004217 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4218 config->sample_rate = req_sample_rate;
4219 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4220 config->channel_mask = req_channel_mask;
4221 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4222 config->format = req_format;
4223 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004224
Haynes Mathew George569b7482017-05-08 14:44:27 -07004225 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004226 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004227 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004228 if (is_hdmi) {
4229 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4230 out->config = pcm_config_hdmi_multi;
4231 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4232 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4233 out->config = pcm_config_mmap_playback;
4234 out->stream.start = out_start;
4235 out->stream.stop = out_stop;
4236 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4237 out->stream.get_mmap_position = out_get_mmap_position;
4238 } else {
4239 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4240 out->config = pcm_config_hifi;
4241 }
4242
4243 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004244 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004245 if (is_hdmi) {
4246 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4247 audio_bytes_per_sample(out->format));
4248 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004249 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004250 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004251 pthread_mutex_lock(&adev->lock);
4252 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4253 pthread_mutex_unlock(&adev->lock);
4254
4255 // reject offload during card offline to allow
4256 // fallback to s/w paths
4257 if (offline) {
4258 ret = -ENODEV;
4259 goto error_open;
4260 }
4261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004262 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4263 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4264 ALOGE("%s: Unsupported Offload information", __func__);
4265 ret = -EINVAL;
4266 goto error_open;
4267 }
4268 if (!is_supported_format(config->offload_info.format)) {
4269 ALOGE("%s: Unsupported audio format", __func__);
4270 ret = -EINVAL;
4271 goto error_open;
4272 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004273 out->sample_rate = config->offload_info.sample_rate;
4274 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4275 out->channel_mask = config->offload_info.channel_mask;
4276 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4277 out->channel_mask = config->channel_mask;
4278 else
4279 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4280
4281 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004282
4283 out->compr_config.codec = (struct snd_codec *)
4284 calloc(1, sizeof(struct snd_codec));
4285
4286 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004287
4288 out->stream.set_callback = out_set_callback;
4289 out->stream.pause = out_pause;
4290 out->stream.resume = out_resume;
4291 out->stream.drain = out_drain;
4292 out->stream.flush = out_flush;
4293
4294 out->compr_config.codec->id =
4295 get_snd_codec_id(config->offload_info.format);
4296 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4297 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004298 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004299 out->compr_config.codec->bit_rate =
4300 config->offload_info.bit_rate;
4301 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004302 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004303 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4304
4305 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4306 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004307
4308 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004309 create_offload_callback_thread(out);
4310 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4311 __func__, config->offload_info.version,
4312 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004313 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4314 switch (config->sample_rate) {
4315 case 0:
4316 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4317 break;
4318 case 8000:
4319 case 16000:
4320 case 48000:
4321 out->sample_rate = config->sample_rate;
4322 break;
4323 default:
4324 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4325 config->sample_rate);
4326 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4327 ret = -EINVAL;
4328 goto error_open;
4329 }
4330 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4331 switch (config->channel_mask) {
4332 case AUDIO_CHANNEL_NONE:
4333 case AUDIO_CHANNEL_OUT_STEREO:
4334 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4335 break;
4336 default:
4337 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4338 config->channel_mask);
4339 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4340 ret = -EINVAL;
4341 goto error_open;
4342 }
4343 switch (config->format) {
4344 case AUDIO_FORMAT_DEFAULT:
4345 case AUDIO_FORMAT_PCM_16_BIT:
4346 out->format = AUDIO_FORMAT_PCM_16_BIT;
4347 break;
4348 default:
4349 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4350 config->format);
4351 config->format = AUDIO_FORMAT_PCM_16_BIT;
4352 ret = -EINVAL;
4353 goto error_open;
4354 }
4355
4356 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004357 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004358 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004359 case 0:
4360 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4361 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004362 case 8000:
4363 case 16000:
4364 case 48000:
4365 out->sample_rate = config->sample_rate;
4366 break;
4367 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004368 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4369 config->sample_rate);
4370 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4371 ret = -EINVAL;
4372 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004373 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004374 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4375 switch (config->channel_mask) {
4376 case AUDIO_CHANNEL_NONE:
4377 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4378 break;
4379 case AUDIO_CHANNEL_OUT_STEREO:
4380 out->channel_mask = config->channel_mask;
4381 break;
4382 default:
4383 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4384 config->channel_mask);
4385 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4386 ret = -EINVAL;
4387 break;
4388 }
4389 switch (config->format) {
4390 case AUDIO_FORMAT_DEFAULT:
4391 out->format = AUDIO_FORMAT_PCM_16_BIT;
4392 break;
4393 case AUDIO_FORMAT_PCM_16_BIT:
4394 out->format = config->format;
4395 break;
4396 default:
4397 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4398 config->format);
4399 config->format = AUDIO_FORMAT_PCM_16_BIT;
4400 ret = -EINVAL;
4401 break;
4402 }
4403 if (ret != 0)
4404 goto error_open;
4405
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004406 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4407 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004408 out->config.rate = out->sample_rate;
4409 out->config.channels =
4410 audio_channel_count_from_out_mask(out->channel_mask);
4411 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004412 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004413 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4414 switch (config->sample_rate) {
4415 case 0:
4416 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4417 break;
4418 case 8000:
4419 case 16000:
4420 case 32000:
4421 case 48000:
4422 out->sample_rate = config->sample_rate;
4423 break;
4424 default:
4425 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4426 config->sample_rate);
4427 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4428 ret = -EINVAL;
4429 break;
4430 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004431 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004432 switch (config->channel_mask) {
4433 case AUDIO_CHANNEL_NONE:
4434 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4435 break;
4436 case AUDIO_CHANNEL_OUT_STEREO:
4437 out->channel_mask = config->channel_mask;
4438 break;
4439 default:
4440 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4441 config->channel_mask);
4442 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4443 ret = -EINVAL;
4444 break;
4445 }
4446 switch (config->format) {
4447 case AUDIO_FORMAT_DEFAULT:
4448 out->format = AUDIO_FORMAT_PCM_16_BIT;
4449 break;
4450 case AUDIO_FORMAT_PCM_16_BIT:
4451 out->format = config->format;
4452 break;
4453 default:
4454 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4455 config->format);
4456 config->format = AUDIO_FORMAT_PCM_16_BIT;
4457 ret = -EINVAL;
4458 break;
4459 }
4460 if (ret != 0)
4461 goto error_open;
4462
vivek mehtaa68fea62017-06-08 19:04:02 -07004463 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004464 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4465 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004466 out->config.rate = out->sample_rate;
4467 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004468 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004469 out->sample_rate,
4470 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004471 out->config.channels,
4472 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004473 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004474 out->config.period_size = buffer_size / frame_size;
4475 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4476 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004478 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004479 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4480 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004481 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004482 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4483 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004484 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004485 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004486 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004487 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004488 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004489 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4490 out->config = pcm_config_mmap_playback;
4491 out->stream.start = out_start;
4492 out->stream.stop = out_stop;
4493 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4494 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004495 } else {
4496 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4497 out->config = pcm_config_low_latency;
4498 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004499
4500 if (config->sample_rate == 0) {
4501 out->sample_rate = out->config.rate;
4502 } else {
4503 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004504 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004505 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4506 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4507 } else {
4508 out->channel_mask = config->channel_mask;
4509 }
4510 if (config->format == AUDIO_FORMAT_DEFAULT)
4511 out->format = audio_format_from_pcm_format(out->config.format);
4512 else if (!audio_is_linear_pcm(config->format)) {
4513 config->format = AUDIO_FORMAT_PCM_16_BIT;
4514 ret = -EINVAL;
4515 goto error_open;
4516 } else {
4517 out->format = config->format;
4518 }
4519
4520 out->config.rate = out->sample_rate;
4521 out->config.channels =
4522 audio_channel_count_from_out_mask(out->channel_mask);
4523 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4524 out->config.format = pcm_format_from_audio_format(out->format);
4525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004527
4528 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4529 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004530 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004531 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4532 __func__, config->sample_rate, config->format, config->channel_mask);
4533 config->sample_rate = out->sample_rate;
4534 config->format = out->format;
4535 config->channel_mask = out->channel_mask;
4536 ret = -EINVAL;
4537 goto error_open;
4538 }
4539
Andy Hung6fcba9c2014-03-18 11:53:32 -07004540 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4541 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004543 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004544 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004545 adev->primary_output = out;
4546 else {
4547 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004548 ret = -EEXIST;
4549 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004550 }
4551 }
4552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553 /* Check if this usecase is already existing */
4554 pthread_mutex_lock(&adev->lock);
4555 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4556 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004558 ret = -EEXIST;
4559 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 }
4561 pthread_mutex_unlock(&adev->lock);
4562
4563 out->stream.common.get_sample_rate = out_get_sample_rate;
4564 out->stream.common.set_sample_rate = out_set_sample_rate;
4565 out->stream.common.get_buffer_size = out_get_buffer_size;
4566 out->stream.common.get_channels = out_get_channels;
4567 out->stream.common.get_format = out_get_format;
4568 out->stream.common.set_format = out_set_format;
4569 out->stream.common.standby = out_standby;
4570 out->stream.common.dump = out_dump;
4571 out->stream.common.set_parameters = out_set_parameters;
4572 out->stream.common.get_parameters = out_get_parameters;
4573 out->stream.common.add_audio_effect = out_add_audio_effect;
4574 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4575 out->stream.get_latency = out_get_latency;
4576 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004577#ifdef NO_AUDIO_OUT
4578 out->stream.write = out_write_for_no_output;
4579#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004580 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004581#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 out->stream.get_render_position = out_get_render_position;
4583 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004584 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004585
Eric Laurent0e46adf2016-12-16 12:49:24 -08004586 if (out->realtime)
4587 out->af_period_multiplier = af_period_multiplier;
4588 else
4589 out->af_period_multiplier = 1;
4590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004592 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004593 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004595 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004596 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004597 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 config->format = out->stream.common.get_format(&out->stream.common);
4600 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4601 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4602
Kevin Rocarda325aa22018-04-03 09:15:52 -07004603 register_format(out->format, out->supported_formats);
4604 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4605 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4606
Andy Hunga452b0a2017-03-15 14:51:15 -07004607 out->error_log = error_log_create(
4608 ERROR_LOG_ENTRIES,
4609 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4610
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004611 /*
4612 By locking output stream before registering, we allow the callback
4613 to update stream's state only after stream's initial state is set to
4614 adev state.
4615 */
4616 lock_output_stream(out);
4617 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4618 pthread_mutex_lock(&adev->lock);
4619 out->card_status = adev->card_status;
4620 pthread_mutex_unlock(&adev->lock);
4621 pthread_mutex_unlock(&out->lock);
4622
vivek mehta4a824772017-06-08 19:05:49 -07004623 stream_app_type_cfg_init(&out->app_type_cfg);
4624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004626
Eric Laurent994a6932013-07-17 11:51:42 -07004627 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004629
4630error_open:
4631 free(out);
4632 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004633 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635}
4636
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004637static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 struct audio_stream_out *stream)
4639{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004640 struct stream_out *out = (struct stream_out *)stream;
4641 struct audio_device *adev = out->dev;
4642
Eric Laurent994a6932013-07-17 11:51:42 -07004643 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004644
4645 // must deregister from sndmonitor first to prevent races
4646 // between the callback and close_stream
4647 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004649 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4650 destroy_offload_callback_thread(out);
4651
4652 if (out->compr_config.codec != NULL)
4653 free(out->compr_config.codec);
4654 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004655
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004656 out->a2dp_compress_mute = false;
4657
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004658 if (adev->voice_tx_output == out)
4659 adev->voice_tx_output = NULL;
4660
Andy Hunga452b0a2017-03-15 14:51:15 -07004661 error_log_destroy(out->error_log);
4662 out->error_log = NULL;
4663
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004664 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004665 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004666 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004668 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004669}
4670
4671static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4672{
4673 struct audio_device *adev = (struct audio_device *)dev;
4674 struct str_parms *parms;
4675 char *str;
4676 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004677 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004679 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004680 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004681
Joe Onorato188b6222016-03-01 11:02:27 -08004682 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004683
4684 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685
4686 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004687 status = voice_set_parameters(adev, parms);
4688 if (status != 0) {
4689 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 }
4691
4692 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4693 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004694 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4696 adev->bluetooth_nrec = true;
4697 else
4698 adev->bluetooth_nrec = false;
4699 }
4700
4701 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4702 if (ret >= 0) {
4703 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4704 adev->screen_off = false;
4705 else
4706 adev->screen_off = true;
4707 }
4708
jasmine cha270b7762018-03-30 15:41:33 +08004709#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004710 ret = str_parms_get_int(parms, "rotation", &val);
4711 if (ret >= 0) {
4712 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004713 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004714 // FIXME: note that the code below assumes that the speakers are in the correct placement
4715 // relative to the user when the device is rotated 90deg from its default rotation. This
4716 // assumption is device-specific, not platform-specific like this code.
4717 case 270:
4718 reverse_speakers = true;
4719 break;
4720 case 0:
4721 case 90:
4722 case 180:
4723 break;
4724 default:
4725 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004726 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004727 }
Eric Laurent03f09432014-03-25 18:09:11 -07004728 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004729 // check and set swap
4730 // - check if orientation changed and speaker active
4731 // - set rotation and cache the rotation value
4732 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004733 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004734 }
jasmine cha270b7762018-03-30 15:41:33 +08004735#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004736
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004737 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4738 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004739 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004740 }
4741
David Linee3fe402017-03-13 10:00:42 -07004742 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4743 if (ret >= 0) {
4744 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004745 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004746 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4747 if (ret >= 0) {
4748 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004749 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004750 }
Eric Laurent99dab492017-06-17 15:19:08 -07004751 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004752 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4753 if (ret >= 0) {
4754 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004755 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004756 }
4757 }
4758 }
4759
4760 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4761 if (ret >= 0) {
4762 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004763 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004764 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4765 if (ret >= 0) {
4766 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004767 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004768 }
Eric Laurent99dab492017-06-17 15:19:08 -07004769 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004770 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4771 if (ret >= 0) {
4772 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004773 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004774 }
4775 }
4776 }
4777
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004778 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004779 audio_extn_ma_set_parameters(adev, parms);
4780
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004781 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4782 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004783 struct audio_usecase *usecase;
4784 struct listnode *node;
4785 list_for_each(node, &adev->usecase_list) {
4786 usecase = node_to_item(node, struct audio_usecase, list);
4787 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004788 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004789 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4790
4791 pthread_mutex_unlock(&adev->lock);
4792 lock_output_stream(usecase->stream.out);
4793 pthread_mutex_lock(&adev->lock);
4794 audio_extn_a2dp_set_handoff_mode(true);
4795 // force device switch to reconfigure encoder
4796 select_devices(adev, usecase->id);
4797 audio_extn_a2dp_set_handoff_mode(false);
4798 pthread_mutex_unlock(&usecase->stream.out->lock);
4799 break;
4800 }
4801 }
4802 }
4803
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004804done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004806 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004807 ALOGV("%s: exit with code(%d)", __func__, status);
4808 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004809}
4810
4811static char* adev_get_parameters(const struct audio_hw_device *dev,
4812 const char *keys)
4813{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004814 struct audio_device *adev = (struct audio_device *)dev;
4815 struct str_parms *reply = str_parms_create();
4816 struct str_parms *query = str_parms_create_str(keys);
4817 char *str;
4818
4819 pthread_mutex_lock(&adev->lock);
4820
4821 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004822 audio_extn_a2dp_get_parameters(query, reply);
4823
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004824 str = str_parms_to_str(reply);
4825 str_parms_destroy(query);
4826 str_parms_destroy(reply);
4827
4828 pthread_mutex_unlock(&adev->lock);
4829 ALOGV("%s: exit: returns - %s", __func__, str);
4830 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831}
4832
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004833static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834{
4835 return 0;
4836}
4837
Haynes Mathew George5191a852013-09-11 14:19:36 -07004838static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4839{
4840 int ret;
4841 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004842
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004843 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4844
Haynes Mathew George5191a852013-09-11 14:19:36 -07004845 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004846 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004847 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004848
Haynes Mathew George5191a852013-09-11 14:19:36 -07004849 return ret;
4850}
4851
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004852static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853{
4854 return -ENOSYS;
4855}
4856
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004857static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4858 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004859{
4860 return -ENOSYS;
4861}
4862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004863static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004864{
4865 return -ENOSYS;
4866}
4867
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004868static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004869{
4870 return -ENOSYS;
4871}
4872
4873static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4874{
4875 struct audio_device *adev = (struct audio_device *)dev;
4876
4877 pthread_mutex_lock(&adev->lock);
4878 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004879 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004880 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004881 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4882 voice_is_in_call(adev)) {
4883 voice_stop_call(adev);
4884 adev->current_call_output = NULL;
4885 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 }
4887 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004888
4889 audio_extn_extspk_set_mode(adev->extspk, mode);
4890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891 return 0;
4892}
4893
4894static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4895{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004896 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898
Eric Laurent2bafff12016-03-17 12:17:23 -07004899 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004900 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004901 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4902 ret = audio_extn_hfp_set_mic_mute(adev, state);
4903 } else {
4904 ret = voice_set_mic_mute(adev, state);
4905 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004906 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004907 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004908
4909 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910}
4911
4912static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4913{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004914 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915 return 0;
4916}
4917
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004918static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 const struct audio_config *config)
4920{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004921 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922
Eric Laurent74b55762017-07-09 17:04:53 -07004923 /* Don't know if USB HIFI in this context so use true to be conservative */
4924 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4925 true /*is_usb_hifi */) != 0)
4926 return 0;
4927
vivek mehtaa68fea62017-06-08 19:04:02 -07004928 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4929 config->sample_rate, config->format,
4930 channel_count,
4931 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932}
4933
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004934static bool adev_input_allow_hifi_record(struct audio_device *adev,
4935 audio_devices_t devices,
4936 audio_input_flags_t flags,
4937 audio_source_t source) {
4938 const bool allowed = true;
4939
4940 if (!audio_is_usb_in_device(devices))
4941 return !allowed;
4942
4943 switch (flags) {
4944 case AUDIO_INPUT_FLAG_NONE:
4945 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4946 break;
4947 default:
4948 return !allowed;
4949 }
4950
4951 switch (source) {
4952 case AUDIO_SOURCE_DEFAULT:
4953 case AUDIO_SOURCE_MIC:
4954 case AUDIO_SOURCE_UNPROCESSED:
4955 break;
4956 default:
4957 return !allowed;
4958 }
4959
4960 switch (adev->mode) {
4961 case 0:
4962 break;
4963 default:
4964 return !allowed;
4965 }
4966
4967 return allowed;
4968}
4969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004971 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004972 audio_devices_t devices,
4973 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004974 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004975 audio_input_flags_t flags,
4976 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004977 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978{
4979 struct audio_device *adev = (struct audio_device *)dev;
4980 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004981 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004982 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004983 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004984 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004985 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4986 devices,
4987 flags,
4988 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004989 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004991
Andy Hungd9653bd2017-08-01 19:31:39 -07004992 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4993 return -ENOSYS;
4994 }
4995
Eric Laurent74b55762017-07-09 17:04:53 -07004996 if (!(is_usb_dev && may_use_hifi_record)) {
4997 if (config->sample_rate == 0)
4998 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4999 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5000 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5001 if (config->format == AUDIO_FORMAT_DEFAULT)
5002 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005003
Eric Laurent74b55762017-07-09 17:04:53 -07005004 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5005
5006 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5007 return -EINVAL;
5008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005009
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005010 if (audio_extn_tfa_98xx_is_supported() &&
5011 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005012 return -EINVAL;
5013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005014 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5015
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005016 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005017 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019 in->stream.common.get_sample_rate = in_get_sample_rate;
5020 in->stream.common.set_sample_rate = in_set_sample_rate;
5021 in->stream.common.get_buffer_size = in_get_buffer_size;
5022 in->stream.common.get_channels = in_get_channels;
5023 in->stream.common.get_format = in_get_format;
5024 in->stream.common.set_format = in_set_format;
5025 in->stream.common.standby = in_standby;
5026 in->stream.common.dump = in_dump;
5027 in->stream.common.set_parameters = in_set_parameters;
5028 in->stream.common.get_parameters = in_get_parameters;
5029 in->stream.common.add_audio_effect = in_add_audio_effect;
5030 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5031 in->stream.set_gain = in_set_gain;
5032 in->stream.read = in_read;
5033 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005034 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005035 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005036
5037 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005038 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005041 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005042 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005044 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
5045 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5046 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5047 /* Force channel config requested to mono if incall
5048 record is being requested for only uplink/downlink */
5049 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5050 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5051 ret = -EINVAL;
5052 goto err_open;
5053 }
5054 }
5055
Haynes Mathew George569b7482017-05-08 14:44:27 -07005056 if (is_usb_dev && may_use_hifi_record) {
5057 /* HiFi record selects an appropriate format, channel, rate combo
5058 depending on sink capabilities*/
5059 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5060 &config->format,
5061 &in->supported_formats[0],
5062 MAX_SUPPORTED_FORMATS,
5063 &config->channel_mask,
5064 &in->supported_channel_masks[0],
5065 MAX_SUPPORTED_CHANNEL_MASKS,
5066 &config->sample_rate,
5067 &in->supported_sample_rates[0],
5068 MAX_SUPPORTED_SAMPLE_RATES);
5069 if (ret != 0) {
5070 ret = -EINVAL;
5071 goto err_open;
5072 }
Eric Laurent74b55762017-07-09 17:04:53 -07005073 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005074 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005075 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005076 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5077 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5078 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5079 bool ret_error = false;
5080 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5081 from HAL is 8_24
5082 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5083 8_24 return error indicating supported format is 8_24
5084 *> In case of any other source requesting 24 bit or float return error
5085 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005086
vivek mehta57ff9b52016-04-28 14:13:08 -07005087 on error flinger will retry with supported format passed
5088 */
5089 if (source != AUDIO_SOURCE_UNPROCESSED) {
5090 config->format = AUDIO_FORMAT_PCM_16_BIT;
5091 ret_error = true;
5092 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5093 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5094 ret_error = true;
5095 }
5096
5097 if (ret_error) {
5098 ret = -EINVAL;
5099 goto err_open;
5100 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005101 }
5102
vivek mehta57ff9b52016-04-28 14:13:08 -07005103 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005104 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005106 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005107 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5108 if (config->sample_rate == 0)
5109 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5110 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5111 config->sample_rate != 8000) {
5112 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5113 ret = -EINVAL;
5114 goto err_open;
5115 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005116
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005117 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5118 config->format = AUDIO_FORMAT_PCM_16_BIT;
5119 ret = -EINVAL;
5120 goto err_open;
5121 }
5122
5123 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5124 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005125 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005126 } else if (is_usb_dev && may_use_hifi_record) {
5127 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5128 in->config = pcm_config_audio_capture;
5129 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005130 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5131 config->sample_rate,
5132 config->format,
5133 channel_count,
5134 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005135 in->config.period_size = buffer_size / frame_size;
5136 in->config.rate = config->sample_rate;
5137 in->af_period_multiplier = 1;
5138 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005139 } else {
5140 in->usecase = USECASE_AUDIO_RECORD;
5141 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005142 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005143 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005144#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005145 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005146#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005147 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005148 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005149 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005150 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005151 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5152 config->sample_rate,
5153 config->format,
5154 channel_count,
5155 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005156 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005157 in->config.rate = config->sample_rate;
5158 in->af_period_multiplier = 1;
5159 } else {
5160 // period size is left untouched for rt mode playback
5161 in->config = pcm_config_audio_capture_rt;
5162 in->af_period_multiplier = af_period_multiplier;
5163 }
5164 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5165 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005166 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005167 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5168 in->config = pcm_config_mmap_capture;
5169 in->stream.start = in_start;
5170 in->stream.stop = in_stop;
5171 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5172 in->stream.get_mmap_position = in_get_mmap_position;
5173 in->af_period_multiplier = 1;
5174 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005175 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005176 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005177 (config->sample_rate == 8000 ||
5178 config->sample_rate == 16000 ||
5179 config->sample_rate == 32000 ||
5180 config->sample_rate == 48000) &&
5181 channel_count == 1) {
5182 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5183 in->config = pcm_config_audio_capture;
5184 frame_size = audio_stream_in_frame_size(&in->stream);
5185 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5186 config->sample_rate,
5187 config->format,
5188 channel_count, false /*is_low_latency*/);
5189 in->config.period_size = buffer_size / frame_size;
5190 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5191 in->config.rate = config->sample_rate;
5192 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005193 } else {
5194 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005195 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005196 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5197 config->sample_rate,
5198 config->format,
5199 channel_count,
5200 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005201 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005202 in->config.rate = config->sample_rate;
5203 in->af_period_multiplier = 1;
5204 }
5205 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5206 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005207 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005209 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005210 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211
Kevin Rocarda325aa22018-04-03 09:15:52 -07005212
5213 register_format(in->format, in->supported_formats);
5214 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5215 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5216
Andy Hungd13f0d32017-06-12 13:58:37 -07005217 in->error_log = error_log_create(
5218 ERROR_LOG_ENTRIES,
5219 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5220
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005221 /* This stream could be for sound trigger lab,
5222 get sound trigger pcm if present */
5223 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005225 lock_input_stream(in);
5226 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5227 pthread_mutex_lock(&adev->lock);
5228 in->card_status = adev->card_status;
5229 pthread_mutex_unlock(&adev->lock);
5230 pthread_mutex_unlock(&in->lock);
5231
vivek mehta4a824772017-06-08 19:05:49 -07005232 stream_app_type_cfg_init(&in->app_type_cfg);
5233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005235 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236 return 0;
5237
5238err_open:
5239 free(in);
5240 *stream_in = NULL;
5241 return ret;
5242}
5243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005244static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 struct audio_stream_in *stream)
5246{
Andy Hungd13f0d32017-06-12 13:58:37 -07005247 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005248 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005249
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005250 // must deregister from sndmonitor first to prevent races
5251 // between the callback and close_stream
5252 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005253 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005254
5255 error_log_destroy(in->error_log);
5256 in->error_log = NULL;
5257
Andy Hung0dbb52b2017-08-09 13:51:38 -07005258 pthread_mutex_destroy(&in->pre_lock);
5259 pthread_mutex_destroy(&in->lock);
5260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261 free(stream);
5262
5263 return;
5264}
5265
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005266static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005267{
5268 return 0;
5269}
5270
Andy Hung31aca912014-03-20 17:14:59 -07005271/* verifies input and output devices and their capabilities.
5272 *
5273 * This verification is required when enabling extended bit-depth or
5274 * sampling rates, as not all qcom products support it.
5275 *
5276 * Suitable for calling only on initialization such as adev_open().
5277 * It fills the audio_device use_case_table[] array.
5278 *
5279 * Has a side-effect that it needs to configure audio routing / devices
5280 * in order to power up the devices and read the device parameters.
5281 * It does not acquire any hw device lock. Should restore the devices
5282 * back to "normal state" upon completion.
5283 */
5284static int adev_verify_devices(struct audio_device *adev)
5285{
5286 /* enumeration is a bit difficult because one really wants to pull
5287 * the use_case, device id, etc from the hidden pcm_device_table[].
5288 * In this case there are the following use cases and device ids.
5289 *
5290 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5291 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005292 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005293 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5294 * [USECASE_AUDIO_RECORD] = {0, 0},
5295 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5296 * [USECASE_VOICE_CALL] = {2, 2},
5297 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005298 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005299 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5300 */
5301
5302 /* should be the usecases enabled in adev_open_input_stream() */
5303 static const int test_in_usecases[] = {
5304 USECASE_AUDIO_RECORD,
5305 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5306 };
5307 /* should be the usecases enabled in adev_open_output_stream()*/
5308 static const int test_out_usecases[] = {
5309 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5310 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5311 };
5312 static const usecase_type_t usecase_type_by_dir[] = {
5313 PCM_PLAYBACK,
5314 PCM_CAPTURE,
5315 };
5316 static const unsigned flags_by_dir[] = {
5317 PCM_OUT,
5318 PCM_IN,
5319 };
5320
5321 size_t i;
5322 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005323 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005324 char info[512]; /* for possible debug info */
5325
5326 for (dir = 0; dir < 2; ++dir) {
5327 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5328 const unsigned flags_dir = flags_by_dir[dir];
5329 const size_t testsize =
5330 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5331 const int *testcases =
5332 dir ? test_in_usecases : test_out_usecases;
5333 const audio_devices_t audio_device =
5334 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5335
5336 for (i = 0; i < testsize; ++i) {
5337 const audio_usecase_t audio_usecase = testcases[i];
5338 int device_id;
5339 snd_device_t snd_device;
5340 struct pcm_params **pparams;
5341 struct stream_out out;
5342 struct stream_in in;
5343 struct audio_usecase uc_info;
5344 int retval;
5345
5346 pparams = &adev->use_case_table[audio_usecase];
5347 pcm_params_free(*pparams); /* can accept null input */
5348 *pparams = NULL;
5349
5350 /* find the device ID for the use case (signed, for error) */
5351 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5352 if (device_id < 0)
5353 continue;
5354
5355 /* prepare structures for device probing */
5356 memset(&uc_info, 0, sizeof(uc_info));
5357 uc_info.id = audio_usecase;
5358 uc_info.type = usecase_type;
5359 if (dir) {
5360 adev->active_input = &in;
5361 memset(&in, 0, sizeof(in));
5362 in.device = audio_device;
5363 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5364 uc_info.stream.in = &in;
5365 } else {
5366 adev->active_input = NULL;
5367 }
5368 memset(&out, 0, sizeof(out));
5369 out.devices = audio_device; /* only field needed in select_devices */
5370 uc_info.stream.out = &out;
5371 uc_info.devices = audio_device;
5372 uc_info.in_snd_device = SND_DEVICE_NONE;
5373 uc_info.out_snd_device = SND_DEVICE_NONE;
5374 list_add_tail(&adev->usecase_list, &uc_info.list);
5375
5376 /* select device - similar to start_(in/out)put_stream() */
5377 retval = select_devices(adev, audio_usecase);
5378 if (retval >= 0) {
5379 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5380#if LOG_NDEBUG == 0
5381 if (*pparams) {
5382 ALOGV("%s: (%s) card %d device %d", __func__,
5383 dir ? "input" : "output", card_id, device_id);
5384 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005385 } else {
5386 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5387 }
5388#endif
5389 }
5390
5391 /* deselect device - similar to stop_(in/out)put_stream() */
5392 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005393 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005394 /* 2. Disable the rx device */
5395 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005396 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005397 list_remove(&uc_info.list);
5398 }
5399 }
5400 adev->active_input = NULL; /* restore adev state */
5401 return 0;
5402}
5403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005404static int adev_close(hw_device_t *device)
5405{
Andy Hung31aca912014-03-20 17:14:59 -07005406 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005407 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005408
5409 if (!adev)
5410 return 0;
5411
5412 pthread_mutex_lock(&adev_init_lock);
5413
5414 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005415 audio_extn_snd_mon_unregister_listener(adev);
5416 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005417 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005418 audio_route_free(adev->audio_route);
5419 free(adev->snd_dev_ref_cnt);
5420 platform_deinit(adev->platform);
5421 audio_extn_extspk_deinit(adev->extspk);
5422 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005423 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005424 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5425 pcm_params_free(adev->use_case_table[i]);
5426 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005427 if (adev->adm_deinit)
5428 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005429 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005430 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005431 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005432
5433 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005435 return 0;
5436}
5437
Glenn Kasten4f993392014-05-14 07:30:48 -07005438/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5439 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5440 * just that it _might_ work.
5441 */
5442static int period_size_is_plausible_for_low_latency(int period_size)
5443{
5444 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005445 case 48:
5446 case 96:
5447 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005448 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005449 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005450 case 240:
5451 case 320:
5452 case 480:
5453 return 1;
5454 default:
5455 return 0;
5456 }
5457}
5458
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005459static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5460{
5461 int card;
5462 card_status_t status;
5463
5464 if (!parms)
5465 return;
5466
5467 if (parse_snd_card_status(parms, &card, &status) < 0)
5468 return;
5469
5470 pthread_mutex_lock(&adev->lock);
5471 bool valid_cb = (card == adev->snd_card);
5472 if (valid_cb) {
5473 if (adev->card_status != status) {
5474 adev->card_status = status;
5475 platform_snd_card_update(adev->platform, status);
5476 }
5477 }
5478 pthread_mutex_unlock(&adev->lock);
5479 return;
5480}
5481
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005482/* out and adev lock held */
5483static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5484{
5485 struct audio_usecase *uc_info;
5486 float left_p;
5487 float right_p;
5488 audio_devices_t devices;
5489
5490 uc_info = get_usecase_from_list(adev, out->usecase);
5491 if (uc_info == NULL) {
5492 ALOGE("%s: Could not find the usecase (%d) in the list",
5493 __func__, out->usecase);
5494 return -EINVAL;
5495 }
5496
5497 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5498 out->usecase, use_case_table[out->usecase]);
5499
5500 if (restore) {
5501 // restore A2DP device for active usecases and unmute if required
5502 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5503 !is_a2dp_device(uc_info->out_snd_device)) {
5504 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5505 select_devices(adev, uc_info->id);
5506 pthread_mutex_lock(&out->compr_mute_lock);
5507 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5508 (out->a2dp_compress_mute)) {
5509 out->a2dp_compress_mute = false;
5510 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5511 }
5512 pthread_mutex_unlock(&out->compr_mute_lock);
5513 }
5514 } else {
5515 // mute compress stream if suspended
5516 pthread_mutex_lock(&out->compr_mute_lock);
5517 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5518 (!out->a2dp_compress_mute)) {
5519 if (!out->standby) {
5520 ALOGD("%s: selecting speaker and muting stream", __func__);
5521 devices = out->devices;
5522 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5523 left_p = out->volume_l;
5524 right_p = out->volume_r;
5525 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5526 compress_pause(out->compr);
5527 set_compr_volume(&out->stream, 0.0f, 0.0f);
5528 out->a2dp_compress_mute = true;
5529 select_devices(adev, out->usecase);
5530 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5531 compress_resume(out->compr);
5532 out->devices = devices;
5533 out->volume_l = left_p;
5534 out->volume_r = right_p;
5535 }
5536 }
5537 pthread_mutex_unlock(&out->compr_mute_lock);
5538 }
5539 ALOGV("%s: exit", __func__);
5540 return 0;
5541}
5542
5543int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5544{
5545 int ret = 0;
5546
5547 lock_output_stream(out);
5548 pthread_mutex_lock(&adev->lock);
5549
5550 ret = check_a2dp_restore_l(adev, out, restore);
5551
5552 pthread_mutex_unlock(&adev->lock);
5553 pthread_mutex_unlock(&out->lock);
5554 return ret;
5555}
5556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005557static int adev_open(const hw_module_t *module, const char *name,
5558 hw_device_t **device)
5559{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005560 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005561
Eric Laurent2bafff12016-03-17 12:17:23 -07005562 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005563 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005564 pthread_mutex_lock(&adev_init_lock);
5565 if (audio_device_ref_count != 0) {
5566 *device = &adev->device.common;
5567 audio_device_ref_count++;
5568 ALOGV("%s: returning existing instance of adev", __func__);
5569 ALOGV("%s: exit", __func__);
5570 pthread_mutex_unlock(&adev_init_lock);
5571 return 0;
5572 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 adev = calloc(1, sizeof(struct audio_device));
5574
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005575 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5578 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5579 adev->device.common.module = (struct hw_module_t *)module;
5580 adev->device.common.close = adev_close;
5581
5582 adev->device.init_check = adev_init_check;
5583 adev->device.set_voice_volume = adev_set_voice_volume;
5584 adev->device.set_master_volume = adev_set_master_volume;
5585 adev->device.get_master_volume = adev_get_master_volume;
5586 adev->device.set_master_mute = adev_set_master_mute;
5587 adev->device.get_master_mute = adev_get_master_mute;
5588 adev->device.set_mode = adev_set_mode;
5589 adev->device.set_mic_mute = adev_set_mic_mute;
5590 adev->device.get_mic_mute = adev_get_mic_mute;
5591 adev->device.set_parameters = adev_set_parameters;
5592 adev->device.get_parameters = adev_get_parameters;
5593 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5594 adev->device.open_output_stream = adev_open_output_stream;
5595 adev->device.close_output_stream = adev_close_output_stream;
5596 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598 adev->device.close_input_stream = adev_close_input_stream;
5599 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005600 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601
5602 /* Set the default route before the PCM stream is opened */
5603 pthread_mutex_lock(&adev->lock);
5604 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005605 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005606 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005607 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005608 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005609 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005610 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005611 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005612 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005613 pthread_mutex_unlock(&adev->lock);
5614
5615 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005616 adev->platform = platform_init(adev);
5617 if (!adev->platform) {
5618 free(adev->snd_dev_ref_cnt);
5619 free(adev);
5620 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5621 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005622 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005623 return -EINVAL;
5624 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005625 adev->extspk = audio_extn_extspk_init(adev);
5626
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005627 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5628 if (adev->visualizer_lib == NULL) {
5629 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5630 } else {
5631 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5632 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005633 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005634 "visualizer_hal_start_output");
5635 adev->visualizer_stop_output =
5636 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5637 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005638 }
5639
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005640 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5641 if (adev->offload_effects_lib == NULL) {
5642 ALOGW("%s: DLOPEN failed for %s", __func__,
5643 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5644 } else {
5645 ALOGV("%s: DLOPEN successful for %s", __func__,
5646 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5647 adev->offload_effects_start_output =
5648 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5649 "offload_effects_bundle_hal_start_output");
5650 adev->offload_effects_stop_output =
5651 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5652 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005653 }
5654
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005655 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5656 if (adev->adm_lib == NULL) {
5657 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5658 } else {
5659 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5660 adev->adm_init = (adm_init_t)
5661 dlsym(adev->adm_lib, "adm_init");
5662 adev->adm_deinit = (adm_deinit_t)
5663 dlsym(adev->adm_lib, "adm_deinit");
5664 adev->adm_register_input_stream = (adm_register_input_stream_t)
5665 dlsym(adev->adm_lib, "adm_register_input_stream");
5666 adev->adm_register_output_stream = (adm_register_output_stream_t)
5667 dlsym(adev->adm_lib, "adm_register_output_stream");
5668 adev->adm_deregister_stream = (adm_deregister_stream_t)
5669 dlsym(adev->adm_lib, "adm_deregister_stream");
5670 adev->adm_request_focus = (adm_request_focus_t)
5671 dlsym(adev->adm_lib, "adm_request_focus");
5672 adev->adm_abandon_focus = (adm_abandon_focus_t)
5673 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005674 adev->adm_set_config = (adm_set_config_t)
5675 dlsym(adev->adm_lib, "adm_set_config");
5676 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5677 dlsym(adev->adm_lib, "adm_request_focus_v2");
5678 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5679 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5680 adev->adm_on_routing_change = (adm_on_routing_change_t)
5681 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005682 }
5683
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005684 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005685 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005687 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005688
Andy Hung31aca912014-03-20 17:14:59 -07005689 if (k_enable_extended_precision)
5690 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691
Glenn Kasten4f993392014-05-14 07:30:48 -07005692 char value[PROPERTY_VALUE_MAX];
5693 int trial;
5694 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5695 trial = atoi(value);
5696 if (period_size_is_plausible_for_low_latency(trial)) {
5697 pcm_config_low_latency.period_size = trial;
5698 pcm_config_low_latency.start_threshold = trial / 4;
5699 pcm_config_low_latency.avail_min = trial / 4;
5700 configured_low_latency_capture_period_size = trial;
5701 }
5702 }
5703 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5704 trial = atoi(value);
5705 if (period_size_is_plausible_for_low_latency(trial)) {
5706 configured_low_latency_capture_period_size = trial;
5707 }
5708 }
5709
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005710 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5711
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005712 // commented as full set of app type cfg is sent from platform
5713 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005714 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005715
5716 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5717 af_period_multiplier = atoi(value);
5718 if (af_period_multiplier < 0) {
5719 af_period_multiplier = 2;
5720 } else if (af_period_multiplier > 4) {
5721 af_period_multiplier = 4;
5722 }
5723 ALOGV("new period_multiplier = %d", af_period_multiplier);
5724 }
5725
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005726 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005727 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005728
vivek mehta1a9b7c02015-06-25 11:49:38 -07005729 pthread_mutex_unlock(&adev_init_lock);
5730
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005731 if (adev->adm_init)
5732 adev->adm_data = adev->adm_init();
5733
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005734 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005735 audio_extn_snd_mon_init();
5736 pthread_mutex_lock(&adev->lock);
5737 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5738 adev->card_status = CARD_STATUS_ONLINE;
5739 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005740 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005741
Eric Laurent2bafff12016-03-17 12:17:23 -07005742 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743 return 0;
5744}
5745
5746static struct hw_module_methods_t hal_module_methods = {
5747 .open = adev_open,
5748};
5749
5750struct audio_module HAL_MODULE_INFO_SYM = {
5751 .common = {
5752 .tag = HARDWARE_MODULE_TAG,
5753 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5754 .hal_api_version = HARDWARE_HAL_API_VERSION,
5755 .id = AUDIO_HARDWARE_MODULE_ID,
5756 .name = "QCOM Audio HAL",
5757 .author = "Code Aurora Forum",
5758 .methods = &hal_module_methods,
5759 },
5760};