blob: 7661e58c8c49b5579078844bacef08763e490a08 [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
juyuchenbe5c67e2018-08-29 17:19:20 +0800543static bool is_supported_24bits_audiosource(audio_source_t source)
544{
545 switch (source) {
546 case AUDIO_SOURCE_UNPROCESSED:
547#ifdef ENABLED_24BITS_CAMCORDER
548 case AUDIO_SOURCE_CAMCORDER:
549#endif
550 return true;
551 default:
552 break;
553 }
554 return false;
555}
556
Haynes Mathew George03c40102016-01-29 17:57:48 -0800557static inline bool is_mmap_usecase(audio_usecase_t uc_id)
558{
559 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
560 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
561}
562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700563static int get_snd_codec_id(audio_format_t format)
564{
565 int id = 0;
566
Eric Laurent8251ac82014-07-23 11:00:25 -0700567 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 case AUDIO_FORMAT_MP3:
569 id = SND_AUDIOCODEC_MP3;
570 break;
571 case AUDIO_FORMAT_AAC:
572 id = SND_AUDIOCODEC_AAC;
573 break;
574 default:
575 ALOGE("%s: Unsupported audio format", __func__);
576 }
577
578 return id;
579}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800580
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800581static int audio_ssr_status(struct audio_device *adev)
582{
583 int ret = 0;
584 struct mixer_ctl *ctl;
585 const char *mixer_ctl_name = "Audio SSR Status";
586
587 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
588 ret = mixer_ctl_get_value(ctl, 0);
589 ALOGD("%s: value: %d", __func__, ret);
590 return ret;
591}
592
vivek mehta4a824772017-06-08 19:05:49 -0700593static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
594{
595 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
596}
597
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800598static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
599{
600 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
601 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
602 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
605 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
606
607}
608
609static bool is_a2dp_device(snd_device_t out_snd_device)
610{
611 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
612}
613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800614int enable_audio_route(struct audio_device *adev,
615 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616{
yixuanjiang509f0a72018-09-06 18:37:23 +0800617 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700618 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800619
620 if (usecase == NULL)
621 return -EINVAL;
622
623 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
624
yixuanjiang509f0a72018-09-06 18:37:23 +0800625 if (usecase->type == PCM_CAPTURE)
626 snd_device = usecase->in_snd_device;
627 else
628 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530629 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800630 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700631
632 // we shouldn't truncate mixer_path
633 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
634 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
635 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800636 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700637
yixuanjiang509f0a72018-09-06 18:37:23 +0800638 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700639 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700640 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642 ALOGV("%s: exit", __func__);
643 return 0;
644}
645
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800646int disable_audio_route(struct audio_device *adev,
647 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800648{
yixuanjiang509f0a72018-09-06 18:37:23 +0800649 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700650 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800651
652 if (usecase == NULL)
653 return -EINVAL;
654
655 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800656 if (usecase->type == PCM_CAPTURE)
657 snd_device = usecase->in_snd_device;
658 else
659 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700660
661 // we shouldn't truncate mixer_path
662 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
663 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
664 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800665 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700666 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700667
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700668 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000669 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 ALOGV("%s: exit", __func__);
672 return 0;
673}
674
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800675int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700676 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700678 int i, num_devices = 0;
679 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800680 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800681 if (snd_device < SND_DEVICE_MIN ||
682 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800683 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800684 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700687 platform_send_audio_calibration(adev->platform, snd_device);
688
vivek mehtade4849c2016-03-03 17:23:38 -0800689 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700690 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700691 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800692 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 }
694
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700695 /* due to the possibility of calibration overwrite between listen
696 and audio, notify sound trigger hal before audio calibration is sent */
697 audio_extn_sound_trigger_update_device_status(snd_device,
698 ST_EVENT_SND_DEVICE_BUSY);
699
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 if (audio_extn_spkr_prot_is_enabled())
701 audio_extn_spkr_prot_calib_cancel(adev);
702
zhaoyang yin4211fad2015-06-04 21:13:25 +0800703 audio_extn_dsm_feedback_enable(adev, snd_device, true);
704
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700705 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800706 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800707 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
709 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700710 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700712 }
713 if (audio_extn_spkr_prot_start_processing(snd_device)) {
714 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800715 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700717 } else if (platform_can_split_snd_device(snd_device,
718 &num_devices,
719 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700720 for (i = 0; i < num_devices; i++) {
721 enable_snd_device(adev, new_snd_devices[i]);
722 }
vivek mehtab6506412015-08-07 16:55:17 -0700723 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700724 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800725 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
726 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
727 ALOGE(" %s: Invalid sound device returned", __func__);
728 goto on_error;
729 }
Ed Tam70b5c142016-03-21 19:14:29 -0700730
Eric Laurent2e140aa2016-06-30 17:14:46 -0700731 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700732
733 if (is_a2dp_device(snd_device) &&
734 (audio_extn_a2dp_start_playback() < 0)) {
735 ALOGE("%s: failed to configure A2DP control path", __func__);
736 goto on_error;
737 }
738
vivek mehtade4849c2016-03-03 17:23:38 -0800739 audio_route_apply_and_update_path(adev->audio_route, device_name);
740 }
741on_success:
742 adev->snd_dev_ref_cnt[snd_device]++;
743 ret_val = 0;
744on_error:
745 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746}
747
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800748int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700749 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700751 int i, num_devices = 0;
752 snd_device_t new_snd_devices[2];
753
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800754 if (snd_device < SND_DEVICE_MIN ||
755 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800756 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 return -EINVAL;
758 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
760 ALOGE("%s: device ref cnt is already 0", __func__);
761 return -EINVAL;
762 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800763 audio_extn_tfa_98xx_disable_speaker(snd_device);
764
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700765 adev->snd_dev_ref_cnt[snd_device]--;
766 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800767 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800768
769 if (is_a2dp_device(snd_device))
770 audio_extn_a2dp_stop_playback();
771
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700772 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800773 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700774 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700775 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
776 audio_extn_spkr_prot_is_enabled()) {
777 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700778
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700779 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
780 // and does not use speaker swap. As this code causes a problem with device enable ref
781 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700782 // when speaker device is disabled, reset swap.
783 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700784 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786 } else if (platform_can_split_snd_device(snd_device,
787 &num_devices,
788 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700789 for (i = 0; i < num_devices; i++) {
790 disable_snd_device(adev, new_snd_devices[i]);
791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700793 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800794 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
795 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE(" %s: Invalid sound device returned", __func__);
797 return -EINVAL;
798 }
799
Eric Laurent2e140aa2016-06-30 17:14:46 -0700800 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800801 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700802 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700803 audio_extn_sound_trigger_update_device_status(snd_device,
804 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 }
vivek mehtab6506412015-08-07 16:55:17 -0700806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 return 0;
808}
809
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700810/*
811 legend:
812 uc - existing usecase
813 new_uc - new usecase
814 d1, d11, d2 - SND_DEVICE enums
815 a1, a2 - corresponding ANDROID device enums
816 B, B1, B2 - backend strings
817
818case 1
819 uc->dev d1 (a1) B1
820 new_uc->dev d1 (a1), d2 (a2) B1, B2
821
822 resolution: disable and enable uc->dev on d1
823
824case 2
825 uc->dev d1 (a1) B1
826 new_uc->dev d11 (a1) B1
827
828 resolution: need to switch uc since d1 and d11 are related
829 (e.g. speaker and voice-speaker)
830 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
831
832case 3
833 uc->dev d1 (a1) B1
834 new_uc->dev d2 (a2) B2
835
836 resolution: no need to switch uc
837
838case 4
839 uc->dev d1 (a1) B
840 new_uc->dev d2 (a2) B
841
842 resolution: disable enable uc-dev on d2 since backends match
843 we cannot enable two streams on two different devices if they
844 share the same backend. e.g. if offload is on speaker device using
845 QUAD_MI2S backend and a low-latency stream is started on voice-handset
846 using the same backend, offload must also be switched to voice-handset.
847
848case 5
849 uc->dev d1 (a1) B
850 new_uc->dev d1 (a1), d2 (a2) B
851
852 resolution: disable enable uc-dev on d2 since backends match
853 we cannot enable two streams on two different devices if they
854 share the same backend.
855
856case 6
857 uc->dev d1 a1 B1
858 new_uc->dev d2 a1 B2
859
860 resolution: no need to switch
861
862case 7
863
864 uc->dev d1 (a1), d2 (a2) B1, B2
865 new_uc->dev d1 B1
866
867 resolution: no need to switch
868
869*/
870static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
871 struct audio_usecase *new_uc,
872 snd_device_t new_snd_device)
873{
874 audio_devices_t a1 = uc->stream.out->devices;
875 audio_devices_t a2 = new_uc->stream.out->devices;
876
877 snd_device_t d1 = uc->out_snd_device;
878 snd_device_t d2 = new_snd_device;
879
880 // Treat as a special case when a1 and a2 are not disjoint
881 if ((a1 != a2) && (a1 & a2)) {
882 snd_device_t d3[2];
883 int num_devices = 0;
884 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
885 &num_devices,
886 d3);
887 if (ret < 0) {
888 if (ret != -ENOSYS) {
889 ALOGW("%s failed to split snd_device %d",
890 __func__,
891 popcount(a1) > 1 ? d1 : d2);
892 }
893 goto end;
894 }
895
896 // NB: case 7 is hypothetical and isn't a practical usecase yet.
897 // But if it does happen, we need to give priority to d2 if
898 // the combo devices active on the existing usecase share a backend.
899 // This is because we cannot have a usecase active on a combo device
900 // and a new usecase requests one device in this combo pair.
901 if (platform_check_backends_match(d3[0], d3[1])) {
902 return d2; // case 5
903 } else {
904 return d1; // case 1
905 }
906 } else {
907 if (platform_check_backends_match(d1, d2)) {
908 return d2; // case 2, 4
909 } else {
910 return d1; // case 6, 3
911 }
912 }
913
914end:
915 return d2; // return whatever was calculated before.
916}
917
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700918static void check_and_route_playback_usecases(struct audio_device *adev,
919 struct audio_usecase *uc_info,
920 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921{
922 struct listnode *node;
923 struct audio_usecase *usecase;
924 bool switch_device[AUDIO_USECASE_MAX];
925 int i, num_uc_to_switch = 0;
926
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700927 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
928 uc_info,
929 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700930
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800931 /* For a2dp device reconfigure all active sessions
932 * with new AFE encoder format based on a2dp state
933 */
934 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700935 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
936 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800937 audio_extn_a2dp_is_force_device_switch()) {
938 force_routing = true;
939 }
940
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 /*
942 * This function is to make sure that all the usecases that are active on
943 * the hardware codec backend are always routed to any one device that is
944 * handled by the hardware codec.
945 * For example, if low-latency and deep-buffer usecases are currently active
946 * on speaker and out_set_parameters(headset) is received on low-latency
947 * output, then we have to make sure deep-buffer is also switched to headset,
948 * because of the limitation that both the devices cannot be enabled
949 * at the same time as they share the same backend.
950 */
951 /* Disable all the usecases on the shared backend other than the
952 specified usecase */
953 for (i = 0; i < AUDIO_USECASE_MAX; i++)
954 switch_device[i] = false;
955
956 list_for_each(node, &adev->usecase_list) {
957 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700958 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
959 continue;
960
961 if (force_routing ||
962 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700963 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
964 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700965 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700966 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
967 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700968 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700969 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 switch_device[usecase->id] = true;
971 num_uc_to_switch++;
972 }
973 }
974
975 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700976 list_for_each(node, &adev->usecase_list) {
977 usecase = node_to_item(node, struct audio_usecase, list);
978 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700979 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900980 }
981 }
982
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700983 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900984 list_for_each(node, &adev->usecase_list) {
985 usecase = node_to_item(node, struct audio_usecase, list);
986 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700987 d_device = derive_playback_snd_device(usecase, uc_info,
988 snd_device);
989 enable_snd_device(adev, d_device);
990 /* Update the out_snd_device before enabling the audio route */
991 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700992 }
993 }
994
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995 /* Re-route all the usecases on the shared backend other than the
996 specified usecase to new snd devices */
997 list_for_each(node, &adev->usecase_list) {
998 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001000 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 }
1002 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001003 }
1004}
1005
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001006static void check_and_route_capture_usecases(struct audio_device *adev,
1007 struct audio_usecase *uc_info,
1008 snd_device_t snd_device)
1009{
1010 struct listnode *node;
1011 struct audio_usecase *usecase;
1012 bool switch_device[AUDIO_USECASE_MAX];
1013 int i, num_uc_to_switch = 0;
1014
vivek mehta4ed66e62016-04-15 23:33:34 -07001015 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1016
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001017 /*
1018 * This function is to make sure that all the active capture usecases
1019 * are always routed to the same input sound device.
1020 * For example, if audio-record and voice-call usecases are currently
1021 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1022 * is received for voice call then we have to make sure that audio-record
1023 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1024 * because of the limitation that two devices cannot be enabled
1025 * at the same time if they share the same backend.
1026 */
1027 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1028 switch_device[i] = false;
1029
1030 list_for_each(node, &adev->usecase_list) {
1031 usecase = node_to_item(node, struct audio_usecase, list);
1032 if (usecase->type != PCM_PLAYBACK &&
1033 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001034 usecase->in_snd_device != snd_device &&
1035 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001036 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1037 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001038 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001039 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001040 switch_device[usecase->id] = true;
1041 num_uc_to_switch++;
1042 }
1043 }
1044
1045 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 list_for_each(node, &adev->usecase_list) {
1047 usecase = node_to_item(node, struct audio_usecase, list);
1048 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001049 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001050 }
1051 }
1052
1053 list_for_each(node, &adev->usecase_list) {
1054 usecase = node_to_item(node, struct audio_usecase, list);
1055 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001056 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001057 }
1058 }
1059
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001060 /* Re-route all the usecases on the shared backend other than the
1061 specified usecase to new snd devices */
1062 list_for_each(node, &adev->usecase_list) {
1063 usecase = node_to_item(node, struct audio_usecase, list);
1064 /* Update the in_snd_device only before enabling the audio route */
1065 if (switch_device[usecase->id] ) {
1066 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001067 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001068 }
1069 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001070 }
1071}
1072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001073/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001074static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001075{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001076 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001077 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078
1079 switch (channels) {
1080 /*
1081 * Do not handle stereo output in Multi-channel cases
1082 * Stereo case is handled in normal playback path
1083 */
1084 case 6:
1085 ALOGV("%s: HDMI supports 5.1", __func__);
1086 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1087 break;
1088 case 8:
1089 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1090 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1091 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1092 break;
1093 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001094 ALOGE("HDMI does not support multi channel playback");
1095 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 break;
1097 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099}
1100
Andy Hung18859412017-08-09 11:47:21 -07001101static ssize_t read_usb_sup_sample_rates(bool is_playback,
1102 uint32_t *supported_sample_rates,
1103 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001104{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001105 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1106 supported_sample_rates,
1107 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001108#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001109 for (ssize_t i=0; i<count; i++) {
1110 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1111 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112 }
1113#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001114 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001115}
1116
Haynes Mathew George569b7482017-05-08 14:44:27 -07001117static int read_usb_sup_channel_masks(bool is_playback,
1118 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001119 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001120{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001121 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001122 int channel_count;
1123 uint32_t num_masks = 0;
1124 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1125 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001126 }
Eric Laurent74b55762017-07-09 17:04:53 -07001127 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001128 // start from 2 channels as framework currently doesn't support mono.
1129 // TODO: consider only supporting channel index masks beyond stereo here.
1130 for (channel_count = FCC_2;
1131 channel_count <= channels && num_masks < max_masks;
1132 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001133 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1134 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001135 for (channel_count = FCC_2;
1136 channel_count <= channels && num_masks < max_masks;
1137 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001138 supported_channel_masks[num_masks++] =
1139 audio_channel_mask_for_index_assignment_from_count(channel_count);
1140 }
1141 } else {
1142 // For capture we report all supported channel masks from 1 channel up.
1143 channel_count = MIN_CHANNEL_COUNT;
1144 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1145 // indexed mask
1146 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001147 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001148 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001149 supported_channel_masks[num_masks++] = mask;
1150 const audio_channel_mask_t index_mask =
1151 audio_channel_mask_for_index_assignment_from_count(channel_count);
1152 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1153 supported_channel_masks[num_masks++] = index_mask;
1154 }
Eric Laurent74b55762017-07-09 17:04:53 -07001155 }
1156 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001157#ifdef NDEBUG
1158 for (size_t i = 0; i < num_masks; ++i) {
1159 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1160 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1161 }
1162#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001163 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001164}
1165
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001166static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001167 audio_format_t *supported_formats,
1168 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001169{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001170 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001171 switch (bitwidth) {
1172 case 24:
1173 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001174 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001175 break;
1176 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001177 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001178 break;
1179 case 16:
1180 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001181 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001182 break;
1183 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001184 ALOGV("%s: %s supported format %d", __func__,
1185 is_playback ? "P" : "C", bitwidth);
1186 return 1;
1187}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001188
Haynes Mathew George569b7482017-05-08 14:44:27 -07001189static int read_usb_sup_params_and_compare(bool is_playback,
1190 audio_format_t *format,
1191 audio_format_t *supported_formats,
1192 uint32_t max_formats,
1193 audio_channel_mask_t *mask,
1194 audio_channel_mask_t *supported_channel_masks,
1195 uint32_t max_masks,
1196 uint32_t *rate,
1197 uint32_t *supported_sample_rates,
1198 uint32_t max_rates) {
1199 int ret = 0;
1200 int num_formats;
1201 int num_masks;
1202 int num_rates;
1203 int i;
1204
1205 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1206 max_formats);
1207 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1208 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001209
Haynes Mathew George569b7482017-05-08 14:44:27 -07001210 num_rates = read_usb_sup_sample_rates(is_playback,
1211 supported_sample_rates, max_rates);
1212
1213#define LUT(table, len, what, dflt) \
1214 for (i=0; i<len && (table[i] != what); i++); \
1215 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1216
1217 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1218 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1219 LUT(supported_sample_rates, num_rates, *rate, 0);
1220
1221#undef LUT
1222 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001223}
1224
Andy Hungd9653bd2017-08-01 19:31:39 -07001225static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1226{
1227 // Check if usb is ready.
1228 // The usb device may have been removed quickly after insertion and hence
1229 // no longer available. This will show up as empty channel masks, or rates.
1230
1231 pthread_mutex_lock(&adev->lock);
1232 uint32_t supported_sample_rate;
1233
1234 // we consider usb ready if we can fetch at least one sample rate.
1235 const bool ready = read_usb_sup_sample_rates(
1236 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1237 pthread_mutex_unlock(&adev->lock);
1238 return ready;
1239}
1240
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001241static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1242{
1243 struct audio_usecase *usecase;
1244 struct listnode *node;
1245
1246 list_for_each(node, &adev->usecase_list) {
1247 usecase = node_to_item(node, struct audio_usecase, list);
1248 if (usecase->type == VOICE_CALL) {
1249 ALOGV("%s: usecase id %d", __func__, usecase->id);
1250 return usecase->id;
1251 }
1252 }
1253 return USECASE_INVALID;
1254}
1255
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001256struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1257 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258{
1259 struct audio_usecase *usecase;
1260 struct listnode *node;
1261
1262 list_for_each(node, &adev->usecase_list) {
1263 usecase = node_to_item(node, struct audio_usecase, list);
1264 if (usecase->id == uc_id)
1265 return usecase;
1266 }
1267 return NULL;
1268}
1269
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001270static bool force_device_switch(struct audio_usecase *usecase)
1271{
1272 if (usecase->stream.out == NULL) {
1273 ALOGE("%s: stream.out is NULL", __func__);
1274 return false;
1275 }
1276
1277 // Force all A2DP output devices to reconfigure for proper AFE encode format
1278 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1279 // in suspended state, hence try to trigger a retry when we again get a routing request.
1280 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1281 audio_extn_a2dp_is_force_device_switch()) {
1282 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1283 return true;
1284 }
1285
1286 return false;
1287}
1288
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001289int select_devices(struct audio_device *adev,
1290 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001292 snd_device_t out_snd_device = SND_DEVICE_NONE;
1293 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001294 struct audio_usecase *usecase = NULL;
1295 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001296 struct audio_usecase *hfp_usecase = NULL;
1297 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001298 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001299 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001300 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1301 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303 usecase = get_usecase_from_list(adev, uc_id);
1304 if (usecase == NULL) {
1305 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1306 return -EINVAL;
1307 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001309 if ((usecase->type == VOICE_CALL) ||
1310 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001311 out_snd_device = platform_get_output_snd_device(adev->platform,
1312 usecase->stream.out->devices);
1313 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001314 usecase->devices = usecase->stream.out->devices;
1315 } else {
1316 /*
1317 * If the voice call is active, use the sound devices of voice call usecase
1318 * so that it would not result any device switch. All the usecases will
1319 * be switched to new device when select_devices() is called for voice call
1320 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001321 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001323 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001324 vc_usecase = get_usecase_from_list(adev,
1325 get_voice_usecase_id_from_list(adev));
1326 if ((vc_usecase != NULL) &&
1327 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1328 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329 in_snd_device = vc_usecase->in_snd_device;
1330 out_snd_device = vc_usecase->out_snd_device;
1331 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001332 } else if (audio_extn_hfp_is_active(adev)) {
1333 hfp_ucid = audio_extn_hfp_get_usecase();
1334 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1335 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1336 in_snd_device = hfp_usecase->in_snd_device;
1337 out_snd_device = hfp_usecase->out_snd_device;
1338 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 }
1340 if (usecase->type == PCM_PLAYBACK) {
1341 usecase->devices = usecase->stream.out->devices;
1342 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001343 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001344 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001345
Eric Laurentb23d5282013-05-14 15:27:20 -07001346 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001347 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001348
1349 if (voip_usecase)
1350 voip_out = voip_usecase->stream.out;
1351
1352 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001353 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001354 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001355 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001356 select_devices(adev, adev->active_input->usecase);
1357 }
1358 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001359 } else if (usecase->type == PCM_CAPTURE) {
1360 usecase->devices = usecase->stream.in->device;
1361 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001362 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001363 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001364 if (adev->active_input &&
1365 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1366 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001367
1368 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1369 USECASE_AUDIO_PLAYBACK_VOIP);
1370
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001371 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001372 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1373 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001374 } else if (voip_usecase) {
1375 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001376 } else if (adev->primary_output) {
1377 out_device = adev->primary_output->devices;
1378 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001379 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001380 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001381 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001382 }
1383 }
1384
1385 if (out_snd_device == usecase->out_snd_device &&
1386 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001387 if (!force_device_switch(usecase))
1388 return 0;
1389 }
1390
1391 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1392 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1393 return 0;
1394 }
1395
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001396 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1397 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001398 (!audio_extn_a2dp_is_ready())) {
1399 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001400 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1401 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1402 else
1403 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 }
1405
juyuchen66c4ecf2018-08-06 15:39:34 +08001406 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1407 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1408 }
1409
Eric Laurent2bafff12016-03-17 12:17:23 -07001410 if (out_snd_device != SND_DEVICE_NONE &&
1411 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1412 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1413 __func__,
1414 use_case_table[uc_id],
1415 adev->last_logged_snd_device[uc_id][0],
1416 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1417 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1418 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1419 -1,
1420 out_snd_device,
1421 platform_get_snd_device_name(out_snd_device),
1422 platform_get_snd_device_acdb_id(out_snd_device));
1423 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1424 }
1425 if (in_snd_device != SND_DEVICE_NONE &&
1426 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1427 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1428 __func__,
1429 use_case_table[uc_id],
1430 adev->last_logged_snd_device[uc_id][1],
1431 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1432 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1433 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1434 -1,
1435 in_snd_device,
1436 platform_get_snd_device_name(in_snd_device),
1437 platform_get_snd_device_acdb_id(in_snd_device));
1438 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1439 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 /*
1442 * Limitation: While in call, to do a device switch we need to disable
1443 * and enable both RX and TX devices though one of them is same as current
1444 * device.
1445 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001446 if ((usecase->type == VOICE_CALL) &&
1447 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1448 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001449 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001450 /* Disable sidetone only if voice call already exists */
1451 if (voice_is_call_state_active(adev))
1452 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001453 }
1454
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001455 /* Disable current sound devices */
1456 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001457 disable_audio_route(adev, usecase);
1458 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 }
1460
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001462 disable_audio_route(adev, usecase);
1463 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 }
1465
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001466 /* Applicable only on the targets that has external modem.
1467 * New device information should be sent to modem before enabling
1468 * the devices to reduce in-call device switch time.
1469 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001470 if ((usecase->type == VOICE_CALL) &&
1471 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1472 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001473 status = platform_switch_voice_call_enable_device_config(adev->platform,
1474 out_snd_device,
1475 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001476 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001477
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 /* Enable new sound devices */
1479 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001480 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001481 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1482 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001483 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001484 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 }
1486
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001487 if (in_snd_device != SND_DEVICE_NONE) {
1488 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001489 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001490 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491
Eric Laurentb23d5282013-05-14 15:27:20 -07001492 if (usecase->type == VOICE_CALL)
1493 status = platform_switch_voice_call_device_post(adev->platform,
1494 out_snd_device,
1495 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001496
sangwoo170731f2013-06-08 15:36:36 +09001497 usecase->in_snd_device = in_snd_device;
1498 usecase->out_snd_device = out_snd_device;
1499
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001500 audio_extn_tfa_98xx_set_mode();
1501
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001502 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001503
Jasmine Cha70771b62018-05-15 15:02:43 +08001504 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001505
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001506 /* Applicable only on the targets that has external modem.
1507 * Enable device command should be sent to modem only after
1508 * enabling voice call mixer controls
1509 */
vivek mehta765eb642015-08-07 19:46:06 -07001510 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001511 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1512 out_snd_device,
1513 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001514 /* Enable sidetone only if voice call already exists */
1515 if (voice_is_call_state_active(adev))
1516 voice_set_sidetone(adev, out_snd_device, true);
1517 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001518
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001519 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001520 struct stream_out *voip_out = voip_usecase->stream.out;
1521 audio_extn_utils_send_app_type_gain(adev,
1522 voip_out->app_type_cfg.app_type,
1523 &voip_out->app_type_cfg.gain[0]);
1524 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 return status;
1526}
1527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528static int stop_input_stream(struct stream_in *in)
1529{
1530 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001531 struct audio_usecase *uc_info;
1532 struct audio_device *adev = in->dev;
1533
Eric Laurent994a6932013-07-17 11:51:42 -07001534 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001536
1537 if (adev->active_input) {
1538 if (adev->active_input->usecase == in->usecase) {
1539 adev->active_input = NULL;
1540 } else {
1541 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1542 __func__,
1543 use_case_table[adev->active_input->usecase],
1544 use_case_table[in->usecase]);
1545 }
1546 }
1547
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001548 uc_info = get_usecase_from_list(adev, in->usecase);
1549 if (uc_info == NULL) {
1550 ALOGE("%s: Could not find the usecase (%d) in the list",
1551 __func__, in->usecase);
1552 return -EINVAL;
1553 }
1554
vivek mehta781065c2017-04-04 12:55:01 -07001555 /* Close in-call recording streams */
1556 voice_check_and_stop_incall_rec_usecase(adev, in);
1557
Eric Laurent150dbfe2013-02-27 14:31:02 -08001558 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001559 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560
1561 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001562 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001564 list_remove(&uc_info->list);
1565 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566
Eric Laurent994a6932013-07-17 11:51:42 -07001567 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 return ret;
1569}
1570
1571int start_input_stream(struct stream_in *in)
1572{
1573 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001574 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001575 struct audio_usecase *uc_info;
1576 struct audio_device *adev = in->dev;
1577
Eric Laurent994a6932013-07-17 11:51:42 -07001578 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001579
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001580 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1581 return -EIO;
1582
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001583 if (in->card_status == CARD_STATUS_OFFLINE ||
1584 adev->card_status == CARD_STATUS_OFFLINE) {
1585 ALOGW("in->card_status or adev->card_status offline, try again");
1586 ret = -EAGAIN;
1587 goto error_config;
1588 }
1589
vivek mehta781065c2017-04-04 12:55:01 -07001590 /* Check if source matches incall recording usecase criteria */
1591 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1592 if (ret)
1593 goto error_config;
1594 else
1595 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1596
Eric Laurentb23d5282013-05-14 15:27:20 -07001597 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 if (in->pcm_device_id < 0) {
1599 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1600 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001601 ret = -EINVAL;
1602 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001603 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604
1605 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1607 uc_info->id = in->usecase;
1608 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001609 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610 uc_info->devices = in->device;
1611 uc_info->in_snd_device = SND_DEVICE_NONE;
1612 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001614 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001615
Wei Wangf4837d52017-11-21 14:51:20 -08001616 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001617 audio_extn_perf_lock_acquire();
1618
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620
Eric Laurent0e46adf2016-12-16 12:49:24 -08001621 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001622 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001623 ALOGE("%s: pcm stream not ready", __func__);
1624 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001625 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001626 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001627 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001628 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1629 goto error_open;
1630 }
1631 } else {
1632 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1633 unsigned int pcm_open_retry_count = 0;
1634
1635 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1636 flags |= PCM_MMAP | PCM_NOIRQ;
1637 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1638 } else if (in->realtime) {
1639 flags |= PCM_MMAP | PCM_NOIRQ;
1640 }
1641
1642 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1643 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1644
1645 while (1) {
1646 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1647 flags, &in->config);
1648 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1649 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1650 if (in->pcm != NULL) {
1651 pcm_close(in->pcm);
1652 in->pcm = NULL;
1653 }
1654 if (pcm_open_retry_count-- == 0) {
1655 ret = -EIO;
1656 goto error_open;
1657 }
1658 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1659 continue;
1660 }
1661 break;
1662 }
1663
1664 ALOGV("%s: pcm_prepare", __func__);
1665 ret = pcm_prepare(in->pcm);
1666 if (ret < 0) {
1667 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001668 pcm_close(in->pcm);
1669 in->pcm = NULL;
1670 goto error_open;
1671 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001672 if (in->realtime) {
1673 ret = pcm_start(in->pcm);
1674 if (ret < 0) {
1675 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1676 pcm_close(in->pcm);
1677 in->pcm = NULL;
1678 goto error_open;
1679 }
1680 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001681 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001682 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001683 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001684 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001685 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001686
Eric Laurent0e46adf2016-12-16 12:49:24 -08001687 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001688
1689error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001691 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001692 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001693
1694error_config:
1695 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001696 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001697 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001698}
1699
Eric Laurenta1478072015-09-21 17:21:52 -07001700void lock_input_stream(struct stream_in *in)
1701{
1702 pthread_mutex_lock(&in->pre_lock);
1703 pthread_mutex_lock(&in->lock);
1704 pthread_mutex_unlock(&in->pre_lock);
1705}
1706
1707void lock_output_stream(struct stream_out *out)
1708{
1709 pthread_mutex_lock(&out->pre_lock);
1710 pthread_mutex_lock(&out->lock);
1711 pthread_mutex_unlock(&out->pre_lock);
1712}
1713
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714/* must be called with out->lock locked */
1715static int send_offload_cmd_l(struct stream_out* out, int command)
1716{
1717 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1718
1719 ALOGVV("%s %d", __func__, command);
1720
1721 cmd->cmd = command;
1722 list_add_tail(&out->offload_cmd_list, &cmd->node);
1723 pthread_cond_signal(&out->offload_cond);
1724 return 0;
1725}
1726
1727/* must be called iwth out->lock locked */
1728static void stop_compressed_output_l(struct stream_out *out)
1729{
1730 out->offload_state = OFFLOAD_STATE_IDLE;
1731 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001732 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 if (out->compr != NULL) {
1734 compress_stop(out->compr);
1735 while (out->offload_thread_blocked) {
1736 pthread_cond_wait(&out->cond, &out->lock);
1737 }
1738 }
1739}
1740
1741static void *offload_thread_loop(void *context)
1742{
1743 struct stream_out *out = (struct stream_out *) context;
1744 struct listnode *item;
1745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1747 set_sched_policy(0, SP_FOREGROUND);
1748 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1749
1750 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001751
Eric Laurenta1478072015-09-21 17:21:52 -07001752 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001753 out->offload_state = OFFLOAD_STATE_IDLE;
1754 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001755 for (;;) {
1756 struct offload_cmd *cmd = NULL;
1757 stream_callback_event_t event;
1758 bool send_callback = false;
1759
1760 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1761 __func__, list_empty(&out->offload_cmd_list),
1762 out->offload_state);
1763 if (list_empty(&out->offload_cmd_list)) {
1764 ALOGV("%s SLEEPING", __func__);
1765 pthread_cond_wait(&out->offload_cond, &out->lock);
1766 ALOGV("%s RUNNING", __func__);
1767 continue;
1768 }
1769
1770 item = list_head(&out->offload_cmd_list);
1771 cmd = node_to_item(item, struct offload_cmd, node);
1772 list_remove(item);
1773
1774 ALOGVV("%s STATE %d CMD %d out->compr %p",
1775 __func__, out->offload_state, cmd->cmd, out->compr);
1776
1777 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1778 free(cmd);
1779 break;
1780 }
1781
1782 if (out->compr == NULL) {
1783 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001784 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785 pthread_cond_signal(&out->cond);
1786 continue;
1787 }
1788 out->offload_thread_blocked = true;
1789 pthread_mutex_unlock(&out->lock);
1790 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001791 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001792 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1793 compress_wait(out->compr, -1);
1794 send_callback = true;
1795 event = STREAM_CBK_EVENT_WRITE_READY;
1796 break;
1797 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798 compress_next_track(out->compr);
1799 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 send_callback = true;
1801 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001802 /* Resend the metadata for next iteration */
1803 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 break;
1805 case OFFLOAD_CMD_DRAIN:
1806 compress_drain(out->compr);
1807 send_callback = true;
1808 event = STREAM_CBK_EVENT_DRAIN_READY;
1809 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001810 case OFFLOAD_CMD_ERROR:
1811 send_callback = true;
1812 event = STREAM_CBK_EVENT_ERROR;
1813 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001814 default:
1815 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1816 break;
1817 }
Eric Laurenta1478072015-09-21 17:21:52 -07001818 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 out->offload_thread_blocked = false;
1820 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001821 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001822 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001824 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001825 free(cmd);
1826 }
1827
1828 pthread_cond_signal(&out->cond);
1829 while (!list_empty(&out->offload_cmd_list)) {
1830 item = list_head(&out->offload_cmd_list);
1831 list_remove(item);
1832 free(node_to_item(item, struct offload_cmd, node));
1833 }
1834 pthread_mutex_unlock(&out->lock);
1835
1836 return NULL;
1837}
1838
1839static int create_offload_callback_thread(struct stream_out *out)
1840{
1841 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1842 list_init(&out->offload_cmd_list);
1843 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1844 offload_thread_loop, out);
1845 return 0;
1846}
1847
1848static int destroy_offload_callback_thread(struct stream_out *out)
1849{
Eric Laurenta1478072015-09-21 17:21:52 -07001850 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001851 stop_compressed_output_l(out);
1852 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1853
1854 pthread_mutex_unlock(&out->lock);
1855 pthread_join(out->offload_thread, (void **) NULL);
1856 pthread_cond_destroy(&out->offload_cond);
1857
1858 return 0;
1859}
1860
Eric Laurent07eeafd2013-10-06 12:52:49 -07001861static bool allow_hdmi_channel_config(struct audio_device *adev)
1862{
1863 struct listnode *node;
1864 struct audio_usecase *usecase;
1865 bool ret = true;
1866
1867 list_for_each(node, &adev->usecase_list) {
1868 usecase = node_to_item(node, struct audio_usecase, list);
1869 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1870 /*
1871 * If voice call is already existing, do not proceed further to avoid
1872 * disabling/enabling both RX and TX devices, CSD calls, etc.
1873 * Once the voice call done, the HDMI channels can be configured to
1874 * max channels of remaining use cases.
1875 */
1876 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001877 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001878 __func__);
1879 ret = false;
1880 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001881 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1882 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001883 "no change in HDMI channels", __func__);
1884 ret = false;
1885 break;
1886 }
1887 }
1888 }
1889 return ret;
1890}
1891
1892static int check_and_set_hdmi_channels(struct audio_device *adev,
1893 unsigned int channels)
1894{
1895 struct listnode *node;
1896 struct audio_usecase *usecase;
1897
1898 /* Check if change in HDMI channel config is allowed */
1899 if (!allow_hdmi_channel_config(adev))
1900 return 0;
1901
1902 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001903 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001904 return 0;
1905 }
1906
1907 platform_set_hdmi_channels(adev->platform, channels);
1908 adev->cur_hdmi_channels = channels;
1909
1910 /*
1911 * Deroute all the playback streams routed to HDMI so that
1912 * the back end is deactivated. Note that backend will not
1913 * be deactivated if any one stream is connected to it.
1914 */
1915 list_for_each(node, &adev->usecase_list) {
1916 usecase = node_to_item(node, struct audio_usecase, list);
1917 if (usecase->type == PCM_PLAYBACK &&
1918 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001919 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001920 }
1921 }
1922
1923 /*
1924 * Enable all the streams disabled above. Now the HDMI backend
1925 * will be activated with new channel configuration
1926 */
1927 list_for_each(node, &adev->usecase_list) {
1928 usecase = node_to_item(node, struct audio_usecase, list);
1929 if (usecase->type == PCM_PLAYBACK &&
1930 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001931 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001932 }
1933 }
1934
1935 return 0;
1936}
1937
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001938static int check_and_set_usb_service_interval(struct audio_device *adev,
1939 struct audio_usecase *uc_info,
1940 bool min)
1941{
1942 struct listnode *node;
1943 struct audio_usecase *usecase;
1944 bool switch_usecases = false;
1945 bool reconfig = false;
1946
1947 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1948 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1949 return -1;
1950
1951 /* set if the valid usecase do not already exist */
1952 list_for_each(node, &adev->usecase_list) {
1953 usecase = node_to_item(node, struct audio_usecase, list);
1954 if (usecase->type == PCM_PLAYBACK &&
1955 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1956 switch (usecase->id) {
1957 case USECASE_AUDIO_PLAYBACK_MMAP:
1958 case USECASE_AUDIO_PLAYBACK_ULL:
1959 // cannot reconfig while mmap/ull is present.
1960 return -1;
1961 default:
1962 switch_usecases = true;
1963 break;
1964 }
1965 }
1966 if (switch_usecases)
1967 break;
1968 }
1969 /*
1970 * client can try to set service interval in start_output_stream
1971 * to min or to 0 (i.e reset) in stop_output_stream .
1972 */
1973 unsigned long service_interval =
1974 audio_extn_usb_find_service_interval(min, true /*playback*/);
1975 int ret = platform_set_usb_service_interval(adev->platform,
1976 true /*playback*/,
1977 service_interval,
1978 &reconfig);
1979 /* no change or not supported or no active usecases */
1980 if (ret || !reconfig || !switch_usecases)
1981 return -1;
1982 return 0;
1983#undef VALID_USECASE
1984}
1985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986static int stop_output_stream(struct stream_out *out)
1987{
1988 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989 struct audio_usecase *uc_info;
1990 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001991 bool has_voip_usecase =
1992 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Eric Laurent994a6932013-07-17 11:51:42 -07001994 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001995 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 uc_info = get_usecase_from_list(adev, out->usecase);
1997 if (uc_info == NULL) {
1998 ALOGE("%s: Could not find the usecase (%d) in the list",
1999 __func__, out->usecase);
2000 return -EINVAL;
2001 }
2002
Haynes Mathew George41f86652014-06-17 14:22:15 -07002003 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2004 if (adev->visualizer_stop_output != NULL)
2005 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2006 if (adev->offload_effects_stop_output != NULL)
2007 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002008 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2009 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2010 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002011 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002012
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002013 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2014 voice_set_device_mute_flag(adev, false);
2015
Eric Laurent150dbfe2013-02-27 14:31:02 -08002016 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002017 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002018
2019 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002020 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002022 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023
Eric Laurent0499d4f2014-08-25 22:39:29 -05002024 audio_extn_extspk_update(adev->extspk);
2025
Eric Laurent07eeafd2013-10-06 12:52:49 -07002026 /* Must be called after removing the usecase from list */
2027 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2028 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002029 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002030 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2031 if (ret == 0) {
2032 /* default service interval was successfully updated,
2033 reopen USB backend with new service interval */
2034 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2035 }
2036 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002037 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002038
HW Lee88512e92018-06-12 15:26:09 +08002039 if (has_voip_usecase ||
2040 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2041 struct listnode *node;
2042 struct audio_usecase *usecase;
2043 list_for_each(node, &adev->usecase_list) {
2044 usecase = node_to_item(node, struct audio_usecase, list);
2045 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2046 continue;
2047
2048 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2049 __func__, usecase->id, use_case_table[usecase->id],
2050 out->usecase, use_case_table[out->usecase]);
2051 select_devices(adev, usecase->id);
2052 }
2053 }
2054
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002055 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002056 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057 return ret;
2058}
2059
2060int start_output_stream(struct stream_out *out)
2061{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002062 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 struct audio_usecase *uc_info;
2064 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002065 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066
Eric Laurent994a6932013-07-17 11:51:42 -07002067 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002068 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002069
2070 if (out->card_status == CARD_STATUS_OFFLINE ||
2071 adev->card_status == CARD_STATUS_OFFLINE) {
2072 ALOGW("out->card_status or adev->card_status offline, try again");
2073 ret = -EAGAIN;
2074 goto error_config;
2075 }
2076
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002077 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2078 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002079 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002080 a2dp_combo = true;
2081 } else {
2082 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2083 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2084 ret = -EAGAIN;
2085 goto error_config;
2086 }
2087 }
2088 }
2089 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002090 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091 if (out->pcm_device_id < 0) {
2092 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2093 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002094 ret = -EINVAL;
2095 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 }
2097
2098 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2099 uc_info->id = out->usecase;
2100 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002101 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002102 uc_info->devices = out->devices;
2103 uc_info->in_snd_device = SND_DEVICE_NONE;
2104 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105
Eric Laurent07eeafd2013-10-06 12:52:49 -07002106 /* This must be called before adding this usecase to the list */
2107 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2108 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002109 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2110 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2111 /* USB backend is not reopened immediately.
2112 This is eventually done as part of select_devices */
2113 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002114
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002115 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116
Wei Wangf4837d52017-11-21 14:51:20 -08002117 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002118 audio_extn_perf_lock_acquire();
2119
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002120 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2121 (!audio_extn_a2dp_is_ready())) {
2122 if (!a2dp_combo) {
2123 check_a2dp_restore_l(adev, out, false);
2124 } else {
2125 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002126 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2127 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2128 else
2129 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002130 select_devices(adev, out->usecase);
2131 out->devices = dev;
2132 }
2133 } else {
2134 select_devices(adev, out->usecase);
2135 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002136
Eric Laurent0499d4f2014-08-25 22:39:29 -05002137 audio_extn_extspk_update(adev->extspk);
2138
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002139 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2140 voice_set_device_mute_flag(adev, true);
2141
Andy Hung31aca912014-03-20 17:14:59 -07002142 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002143 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002144 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2145 out->pcm = NULL;
2146 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2147 COMPRESS_IN, &out->compr_config);
2148 if (out->compr && !is_compress_ready(out->compr)) {
2149 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2150 compress_close(out->compr);
2151 out->compr = NULL;
2152 ret = -EIO;
2153 goto error_open;
2154 }
2155 if (out->offload_callback)
2156 compress_nonblock(out->compr, out->non_blocking);
2157
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002158 if (adev->visualizer_start_output != NULL) {
2159 int capture_device_id =
2160 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2161 PCM_CAPTURE);
2162 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2163 adev->snd_card, capture_device_id);
2164 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002165 if (adev->offload_effects_start_output != NULL)
2166 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2167 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002168 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002169 ALOGE("%s: pcm stream not ready", __func__);
2170 goto error_open;
2171 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002172 ret = pcm_start(out->pcm);
2173 if (ret < 0) {
2174 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2175 goto error_open;
2176 }
2177 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002178 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002179 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002180
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002181 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2182 flags |= PCM_MMAP | PCM_NOIRQ;
2183 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002184 } else if (out->realtime) {
2185 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002186 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002187
2188 while (1) {
2189 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2190 flags, &out->config);
2191 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2192 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2193 if (out->pcm != NULL) {
2194 pcm_close(out->pcm);
2195 out->pcm = NULL;
2196 }
2197 if (pcm_open_retry_count-- == 0) {
2198 ret = -EIO;
2199 goto error_open;
2200 }
2201 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2202 continue;
2203 }
2204 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002205 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002206 ALOGV("%s: pcm_prepare", __func__);
2207 if (pcm_is_ready(out->pcm)) {
2208 ret = pcm_prepare(out->pcm);
2209 if (ret < 0) {
2210 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2211 pcm_close(out->pcm);
2212 out->pcm = NULL;
2213 goto error_open;
2214 }
2215 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002216 if (out->realtime) {
2217 ret = pcm_start(out->pcm);
2218 if (ret < 0) {
2219 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2220 pcm_close(out->pcm);
2221 out->pcm = NULL;
2222 goto error_open;
2223 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002224 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002225 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002226 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002227 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002228 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002229 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002230
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002231 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2232 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2233 audio_low_latency_hint_start();
2234 }
2235
vivek mehtae59cfb22017-06-16 15:57:11 -07002236 // consider a scenario where on pause lower layers are tear down.
2237 // so on resume, swap mixer control need to be sent only when
2238 // backend is active, hence rather than sending from enable device
2239 // sending it from start of streamtream
2240
2241 platform_set_swap_channels(adev, true);
2242
Eric Laurent994a6932013-07-17 11:51:42 -07002243 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002244 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002245error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002246 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002247 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002249error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002250 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251}
2252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253static int check_input_parameters(uint32_t sample_rate,
2254 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002255 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002257 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2258 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002259 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2260 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002261 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2262 return -EINVAL;
2263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264
Eric Laurent74b55762017-07-09 17:04:53 -07002265 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2266 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002267 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002268 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002269 return -EINVAL;
2270 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271
2272 switch (sample_rate) {
2273 case 8000:
2274 case 11025:
2275 case 12000:
2276 case 16000:
2277 case 22050:
2278 case 24000:
2279 case 32000:
2280 case 44100:
2281 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002282 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283 break;
2284 default:
vivek mehtadae44712015-07-27 14:13:18 -07002285 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 return -EINVAL;
2287 }
2288
2289 return 0;
2290}
2291
Kevin Rocarda325aa22018-04-03 09:15:52 -07002292/** Add a value in a list if not already present.
2293 * @return true if value was successfully inserted or already present,
2294 * false if the list is full and does not contain the value.
2295 */
2296static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2297 for (size_t i = 0; i < list_length; i++) {
2298 if (list[i] == value) return true; // value is already present
2299 if (list[i] == 0) { // no values in this slot
2300 list[i] = value;
2301 return true; // value inserted
2302 }
2303 }
2304 return false; // could not insert value
2305}
2306
2307/** Add channel_mask in supported_channel_masks if not already present.
2308 * @return true if channel_mask was successfully inserted or already present,
2309 * false if supported_channel_masks is full and does not contain channel_mask.
2310 */
2311static void register_channel_mask(audio_channel_mask_t channel_mask,
2312 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2313 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2314 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2315}
2316
2317/** Add format in supported_formats if not already present.
2318 * @return true if format was successfully inserted or already present,
2319 * false if supported_formats is full and does not contain format.
2320 */
2321static void register_format(audio_format_t format,
2322 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2323 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2324 "%s: stream can not declare supporting its format %x", __func__, format);
2325}
2326/** Add sample_rate in supported_sample_rates if not already present.
2327 * @return true if sample_rate was successfully inserted or already present,
2328 * false if supported_sample_rates is full and does not contain sample_rate.
2329 */
2330static void register_sample_rate(uint32_t sample_rate,
2331 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2332 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2333 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2334}
2335
vivek mehtaa68fea62017-06-08 19:04:02 -07002336static size_t get_stream_buffer_size(size_t duration_ms,
2337 uint32_t sample_rate,
2338 audio_format_t format,
2339 int channel_count,
2340 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341{
2342 size_t size = 0;
2343
vivek mehtaa68fea62017-06-08 19:04:02 -07002344 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002345 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002346 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002347
2348 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349
Glenn Kasten4f993392014-05-14 07:30:48 -07002350 /* make sure the size is multiple of 32 bytes
2351 * At 48 kHz mono 16-bit PCM:
2352 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2353 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2354 */
2355 size += 0x1f;
2356 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002357
2358 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359}
2360
2361static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2362{
2363 struct stream_out *out = (struct stream_out *)stream;
2364
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002365 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366}
2367
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002368static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002369{
2370 return -ENOSYS;
2371}
2372
2373static size_t out_get_buffer_size(const struct audio_stream *stream)
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
2376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2378 return out->compr_config.fragment_size;
2379 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002380 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002381 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382}
2383
2384static uint32_t out_get_channels(const struct audio_stream *stream)
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387
2388 return out->channel_mask;
2389}
2390
2391static audio_format_t out_get_format(const struct audio_stream *stream)
2392{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 struct stream_out *out = (struct stream_out *)stream;
2394
2395 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396}
2397
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002398static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399{
2400 return -ENOSYS;
2401}
2402
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002403/* must be called with out->lock locked */
2404static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405{
2406 struct stream_out *out = (struct stream_out *)stream;
2407 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002408 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002410 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002411 if (adev->adm_deregister_stream)
2412 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002413 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2416 if (out->pcm) {
2417 pcm_close(out->pcm);
2418 out->pcm = NULL;
2419 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002420 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002421 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002422 out->playback_started = false;
2423 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 } else {
2425 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002426 out->gapless_mdata.encoder_delay = 0;
2427 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002428 if (out->compr != NULL) {
2429 compress_close(out->compr);
2430 out->compr = NULL;
2431 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002432 }
Phil Burkbc991042017-02-24 08:06:44 -08002433 if (do_stop) {
2434 stop_output_stream(out);
2435 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002436 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002438 return 0;
2439}
2440
2441static int out_standby(struct audio_stream *stream)
2442{
2443 struct stream_out *out = (struct stream_out *)stream;
2444
2445 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2446 out->usecase, use_case_table[out->usecase]);
2447
2448 lock_output_stream(out);
2449 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002451 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 return 0;
2453}
2454
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002455static int out_on_error(struct audio_stream *stream)
2456{
2457 struct stream_out *out = (struct stream_out *)stream;
2458 struct audio_device *adev = out->dev;
2459 bool do_standby = false;
2460
2461 lock_output_stream(out);
2462 if (!out->standby) {
2463 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2464 stop_compressed_output_l(out);
2465 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2466 } else
2467 do_standby = true;
2468 }
2469 pthread_mutex_unlock(&out->lock);
2470
2471 if (do_standby)
2472 return out_standby(&out->stream.common);
2473
2474 return 0;
2475}
2476
Andy Hung7401c7c2016-09-21 12:41:21 -07002477static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478{
Andy Hung7401c7c2016-09-21 12:41:21 -07002479 struct stream_out *out = (struct stream_out *)stream;
2480
2481 // We try to get the lock for consistency,
2482 // but it isn't necessary for these variables.
2483 // If we're not in standby, we may be blocked on a write.
2484 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2485 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2486 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2487
2488 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002489 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002490 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002491
2492 // dump error info
2493 (void)error_log_dump(
2494 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 return 0;
2497}
2498
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002499static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2500{
2501 int ret = 0;
2502 char value[32];
2503 struct compr_gapless_mdata tmp_mdata;
2504
2505 if (!out || !parms) {
2506 return -EINVAL;
2507 }
2508
2509 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2510 if (ret >= 0) {
2511 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2512 } else {
2513 return -EINVAL;
2514 }
2515
2516 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2517 if (ret >= 0) {
2518 tmp_mdata.encoder_padding = atoi(value);
2519 } else {
2520 return -EINVAL;
2521 }
2522
2523 out->gapless_mdata = tmp_mdata;
2524 out->send_new_metadata = 1;
2525 ALOGV("%s new encoder delay %u and padding %u", __func__,
2526 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2527
2528 return 0;
2529}
2530
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002531static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2532{
2533 return out == adev->primary_output || out == adev->voice_tx_output;
2534}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002535
Kevin Rocard1e02c882017-08-09 15:26:07 -07002536static int get_alive_usb_card(struct str_parms* parms) {
2537 int card;
2538 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2539 !audio_extn_usb_alive(card)) {
2540 return card;
2541 }
2542 return -ENODEV;
2543}
2544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2546{
2547 struct stream_out *out = (struct stream_out *)stream;
2548 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002549 struct audio_usecase *usecase;
2550 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551 struct str_parms *parms;
2552 char value[32];
2553 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002554 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002555 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002556 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557
Eric Laurent2e140aa2016-06-30 17:14:46 -07002558 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002559 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 parms = str_parms_create_str(kvpairs);
2561 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2562 if (ret >= 0) {
2563 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002564
Eric Laurenta1478072015-09-21 17:21:52 -07002565 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002566
2567 // The usb driver needs to be closed after usb device disconnection
2568 // otherwise audio is no longer played on the new usb devices.
2569 // By forcing the stream in standby, the usb stack refcount drops to 0
2570 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002571 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002572 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002573 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2574 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2575 out_standby_l(&out->stream.common);
2576 }
2577 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002578 }
2579
Eric Laurent150dbfe2013-02-27 14:31:02 -08002580 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002581
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002582 /*
2583 * When HDMI cable is unplugged the music playback is paused and
2584 * the policy manager sends routing=0. But the audioflinger
2585 * continues to write data until standby time (3sec).
2586 * As the HDMI core is turned off, the write gets blocked.
2587 * Avoid this by routing audio to speaker until standby.
2588 */
2589 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2590 val == AUDIO_DEVICE_NONE) {
2591 val = AUDIO_DEVICE_OUT_SPEAKER;
2592 }
2593
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002594 /*
2595 * When A2DP is disconnected the
2596 * music playback is paused and the policy manager sends routing=0
2597 * But the audioflingercontinues to write data until standby time
2598 * (3sec). As BT is turned off, the write gets blocked.
2599 * Avoid this by routing audio to speaker until standby.
2600 */
2601 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2602 (val == AUDIO_DEVICE_NONE) &&
2603 !audio_extn_a2dp_is_ready()) {
2604 val = AUDIO_DEVICE_OUT_SPEAKER;
2605 }
2606
2607 /* To avoid a2dp to sco overlapping / BT device improper state
2608 * check with BT lib about a2dp streaming support before routing
2609 */
2610 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2611 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002612 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002613 //combo usecase just by pass a2dp
2614 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2615 bypass_a2dp = true;
2616 } else {
2617 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2618 /* update device to a2dp and don't route as BT returned error
2619 * However it is still possible a2dp routing called because
2620 * of current active device disconnection (like wired headset)
2621 */
2622 out->devices = val;
2623 pthread_mutex_unlock(&out->lock);
2624 pthread_mutex_unlock(&adev->lock);
2625 status = -ENOSYS;
2626 goto routing_fail;
2627 }
2628 }
2629 }
2630
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002631 audio_devices_t new_dev = val;
2632
2633 // Workaround: If routing to an non existing usb device, fail gracefully
2634 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002635 int card;
2636 if (audio_is_usb_out_device(new_dev) &&
2637 (card = get_alive_usb_card(parms)) >= 0) {
2638
2639 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002640 pthread_mutex_unlock(&adev->lock);
2641 pthread_mutex_unlock(&out->lock);
2642 status = -ENOSYS;
2643 goto routing_fail;
2644 }
2645
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002646 /*
2647 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002648 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002649 * the select_devices(). But how do we undo this?
2650 *
2651 * For example, music playback is active on headset (deep-buffer usecase)
2652 * and if we go to ringtones and select a ringtone, low-latency usecase
2653 * will be started on headset+speaker. As we can't enable headset+speaker
2654 * and headset devices at the same time, select_devices() switches the music
2655 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2656 * So when the ringtone playback is completed, how do we undo the same?
2657 *
2658 * We are relying on the out_set_parameters() call on deep-buffer output,
2659 * once the ringtone playback is ended.
2660 * NOTE: We should not check if the current devices are same as new devices.
2661 * Because select_devices() must be called to switch back the music
2662 * playback to headset.
2663 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002664 if (new_dev != AUDIO_DEVICE_NONE) {
2665 bool same_dev = out->devices == new_dev;
2666 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667
Eric Laurenta7657192014-10-09 21:09:33 -07002668 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002669 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002670 if (adev->mode == AUDIO_MODE_IN_CALL) {
2671 adev->current_call_output = out;
2672 ret = voice_start_call(adev);
2673 }
2674 } else {
2675 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002676 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002677 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002678 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002679
2680 if (!out->standby) {
2681 if (!same_dev) {
2682 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002683 // inform adm before actual routing to prevent glitches.
2684 if (adev->adm_on_routing_change) {
2685 adev->adm_on_routing_change(adev->adm_data,
2686 out->handle);
2687 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002688 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002689 if (!bypass_a2dp) {
2690 select_devices(adev, out->usecase);
2691 } else {
juyuchen9baad392018-06-05 19:02:10 +08002692 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2693 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2694 else
2695 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002696 select_devices(adev, out->usecase);
2697 out->devices = new_dev;
2698 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002699 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002700
2701 // on device switch force swap, lower functions will make sure
2702 // to check if swap is allowed or not.
2703
2704 if (!same_dev)
2705 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002706
2707 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2708 out->a2dp_compress_mute &&
2709 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2710 pthread_mutex_lock(&out->compr_mute_lock);
2711 out->a2dp_compress_mute = false;
2712 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2713 pthread_mutex_unlock(&out->compr_mute_lock);
2714 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002715 }
2716
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002717 }
2718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002719 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002720 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002721
2722 /*handles device and call state changes*/
2723 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002725 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002726
2727 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2728 parse_compress_metadata(out, parms);
2729 }
2730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002732 ALOGV("%s: exit: code(%d)", __func__, status);
2733 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734}
2735
Haynes Mathew George569b7482017-05-08 14:44:27 -07002736static bool stream_get_parameter_channels(struct str_parms *query,
2737 struct str_parms *reply,
2738 audio_channel_mask_t *supported_channel_masks) {
2739 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002740 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002742 size_t i, j;
2743
2744 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2745 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 value[0] = '\0';
2747 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002748 while (supported_channel_masks[i] != 0) {
2749 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2750 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 if (!first) {
2752 strcat(value, "|");
2753 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002754 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 first = false;
2756 break;
2757 }
2758 }
2759 i++;
2760 }
2761 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002762 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763 return ret >= 0;
2764}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002765
Haynes Mathew George569b7482017-05-08 14:44:27 -07002766static bool stream_get_parameter_formats(struct str_parms *query,
2767 struct str_parms *reply,
2768 audio_format_t *supported_formats) {
2769 int ret = -1;
2770 char value[256];
2771 int i;
2772
2773 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2774 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002775 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002776 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002777 case AUDIO_FORMAT_PCM_16_BIT:
2778 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2779 break;
2780 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2781 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2782 break;
2783 case AUDIO_FORMAT_PCM_32_BIT:
2784 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2785 break;
2786 default:
2787 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002788 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002789 break;
2790 }
2791 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002792 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002793 return ret >= 0;
2794}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002795
Haynes Mathew George569b7482017-05-08 14:44:27 -07002796static bool stream_get_parameter_rates(struct str_parms *query,
2797 struct str_parms *reply,
2798 uint32_t *supported_sample_rates) {
2799
2800 int i;
2801 char value[256];
2802 int ret = -1;
2803 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2804 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002805 value[0] = '\0';
2806 i=0;
2807 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002808 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002809 int avail = sizeof(value) - cursor;
2810 ret = snprintf(value + cursor, avail, "%s%d",
2811 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002812 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002813 if (ret < 0 || ret >= avail) {
2814 // if cursor is at the last element of the array
2815 // overwrite with \0 is duplicate work as
2816 // snprintf already put a \0 in place.
2817 // else
2818 // we had space to write the '|' at value[cursor]
2819 // (which will be overwritten) or no space to fill
2820 // the first element (=> cursor == 0)
2821 value[cursor] = '\0';
2822 break;
2823 }
2824 cursor += ret;
2825 ++i;
2826 }
2827 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2828 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002829 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002830 return ret >= 0;
2831}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002832
Haynes Mathew George569b7482017-05-08 14:44:27 -07002833static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2834{
2835 struct stream_out *out = (struct stream_out *)stream;
2836 struct str_parms *query = str_parms_create_str(keys);
2837 char *str;
2838 struct str_parms *reply = str_parms_create();
2839 bool replied = false;
2840 ALOGV("%s: enter: keys - %s", __func__, keys);
2841
2842 replied |= stream_get_parameter_channels(query, reply,
2843 &out->supported_channel_masks[0]);
2844 replied |= stream_get_parameter_formats(query, reply,
2845 &out->supported_formats[0]);
2846 replied |= stream_get_parameter_rates(query, reply,
2847 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002848 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 str = str_parms_to_str(reply);
2850 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002851 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002852 }
2853 str_parms_destroy(query);
2854 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002855 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 return str;
2857}
2858
2859static uint32_t out_get_latency(const struct audio_stream_out *stream)
2860{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002861 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002863 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2866 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002867 else if ((out->realtime) ||
2868 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002869 // since the buffer won't be filled up faster than realtime,
2870 // return a smaller number
2871 period_ms = (out->af_period_multiplier * out->config.period_size *
2872 1000) / (out->config.rate);
2873 hw_delay = platform_render_latency(out->usecase)/1000;
2874 return period_ms + hw_delay;
2875 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002877 latency = (out->config.period_count * out->config.period_size * 1000) /
2878 (out->config.rate);
2879
2880 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2881 latency += audio_extn_a2dp_get_encoder_latency();
2882
2883 return latency;
2884}
2885
2886static int set_compr_volume(struct audio_stream_out *stream, float left,
2887 float right)
2888{
2889 struct stream_out *out = (struct stream_out *)stream;
2890 int volume[2];
2891 char mixer_ctl_name[128];
2892 struct audio_device *adev = out->dev;
2893 struct mixer_ctl *ctl;
2894 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2895 PCM_PLAYBACK);
2896
2897 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2898 "Compress Playback %d Volume", pcm_device_id);
2899 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2900 if (!ctl) {
2901 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2902 __func__, mixer_ctl_name);
2903 return -EINVAL;
2904 }
2905 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2906 __func__, mixer_ctl_name, left, right);
2907 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2908 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2909 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2910
2911 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002912}
2913
2914static int out_set_volume(struct audio_stream_out *stream, float left,
2915 float right)
2916{
Eric Laurenta9024de2013-04-04 09:19:12 -07002917 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002918 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002920 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002921 /* only take left channel into account: the API is for stereo anyway */
2922 out->muted = (left == 0.0f);
2923 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002924 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002925 pthread_mutex_lock(&out->compr_mute_lock);
2926 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2927 if (!out->a2dp_compress_mute)
2928 ret = set_compr_volume(stream, left, right);
2929 out->volume_l = left;
2930 out->volume_r = right;
2931 pthread_mutex_unlock(&out->compr_mute_lock);
2932 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002933 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002934 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2935 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2936 if (!out->standby) {
2937 // if in standby, cached volume will be sent after stream is opened
2938 audio_extn_utils_send_app_type_gain(out->dev,
2939 out->app_type_cfg.app_type,
2940 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002941 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002942 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002943 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 return -ENOSYS;
2946}
2947
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002948// note: this call is safe only if the stream_cb is
2949// removed first in close_output_stream (as is done now).
2950static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2951{
2952 if (!stream || !parms)
2953 return;
2954
2955 struct stream_out *out = (struct stream_out *)stream;
2956 struct audio_device *adev = out->dev;
2957
2958 card_status_t status;
2959 int card;
2960 if (parse_snd_card_status(parms, &card, &status) < 0)
2961 return;
2962
2963 pthread_mutex_lock(&adev->lock);
2964 bool valid_cb = (card == adev->snd_card);
2965 pthread_mutex_unlock(&adev->lock);
2966
2967 if (!valid_cb)
2968 return;
2969
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002970 lock_output_stream(out);
2971 if (out->card_status != status)
2972 out->card_status = status;
2973 pthread_mutex_unlock(&out->lock);
2974
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002975 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2976 use_case_table[out->usecase],
2977 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2978
2979 if (status == CARD_STATUS_OFFLINE)
2980 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002981
2982 return;
2983}
2984
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002985#ifdef NO_AUDIO_OUT
2986static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002987 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002988{
2989 struct stream_out *out = (struct stream_out *)stream;
2990
2991 /* No Output device supported other than BT for playback.
2992 * Sleep for the amount of buffer duration
2993 */
Eric Laurenta1478072015-09-21 17:21:52 -07002994 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002995 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2996 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002997 out_get_sample_rate(&out->stream.common));
2998 pthread_mutex_unlock(&out->lock);
2999 return bytes;
3000}
3001#endif
3002
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3004 size_t bytes)
3005{
3006 struct stream_out *out = (struct stream_out *)stream;
3007 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003008 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003009 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003010
Eric Laurenta1478072015-09-21 17:21:52 -07003011 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003012 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003013 const size_t frame_size = audio_stream_out_frame_size(stream);
3014 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003015
Eric Laurent0e46adf2016-12-16 12:49:24 -08003016 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3017 error_code = ERROR_CODE_WRITE;
3018 goto exit;
3019 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003020
3021 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3022 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003023 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003024 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3025 ret = -EIO;
3026 goto exit;
3027 }
3028 }
3029 }
3030
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003032 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003033 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003038 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003039 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 goto exit;
3041 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003042
vivek mehta40125092017-08-21 18:48:51 -07003043 // after standby always force set last known cal step
3044 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3045 ALOGD("%s: retry previous failed cal level set", __func__);
3046 send_gain_dep_calibration_l();
3047 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003050 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003051 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003052 if (out->send_new_metadata) {
3053 ALOGVV("send new gapless metadata");
3054 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3055 out->send_new_metadata = 0;
3056 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003057 unsigned int avail;
3058 struct timespec tstamp;
3059 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3060 /* Do not limit write size if the available frames count is unknown */
3061 if (ret != 0) {
3062 avail = bytes;
3063 }
3064 if (avail == 0) {
3065 ret = 0;
3066 } else {
3067 if (avail > bytes) {
3068 avail = bytes;
3069 }
3070 ret = compress_write(out->compr, buffer, avail);
3071 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3072 __func__, avail, ret);
3073 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003074
Eric Laurent6e895242013-09-05 16:10:57 -07003075 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3077 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003078 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 compress_start(out->compr);
3080 out->playback_started = 1;
3081 out->offload_state = OFFLOAD_STATE_PLAYING;
3082 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003083 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003084 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003085 } else {
3086 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003087 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003089 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 return ret;
3091 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003092 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003094 size_t bytes_to_write = bytes;
3095
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 if (out->muted)
3097 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003098 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003099 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003100 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3101 int16_t *src = (int16_t *)buffer;
3102 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003103
Eric Laurentad2dde92017-09-20 18:27:31 -07003104 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3105 out->format != AUDIO_FORMAT_PCM_16_BIT,
3106 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003107
Eric Laurentad2dde92017-09-20 18:27:31 -07003108 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3109 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3110 }
3111 bytes_to_write /= 2;
3112 }
3113 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3114
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003115 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003116 request_out_focus(out, ns);
3117
3118 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3119 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003120 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003121 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003122 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003123
Haynes Mathew George03c40102016-01-29 17:57:48 -08003124 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003125 } else {
3126 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 }
3129
3130exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003131 // For PCM we always consume the buffer and return #bytes regardless of ret.
3132 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003133 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003134 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003135 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003136
Andy Hung7401c7c2016-09-21 12:41:21 -07003137 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003138 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003139 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3140 ALOGE_IF(out->pcm != NULL,
3141 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003142 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003143 // usleep not guaranteed for values over 1 second but we don't limit here.
3144 }
3145 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 pthread_mutex_unlock(&out->lock);
3148
3149 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003150 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003151 if (sleeptime_us != 0)
3152 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153 }
3154 return bytes;
3155}
3156
3157static int out_get_render_position(const struct audio_stream_out *stream,
3158 uint32_t *dsp_frames)
3159{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 struct stream_out *out = (struct stream_out *)stream;
3161 *dsp_frames = 0;
3162 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003163 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003164 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003165 unsigned long frames = 0;
3166 // TODO: check return value
3167 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3168 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003169 ALOGVV("%s rendered frames %d sample_rate %d",
3170 __func__, *dsp_frames, out->sample_rate);
3171 }
3172 pthread_mutex_unlock(&out->lock);
3173 return 0;
3174 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003175 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176}
3177
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003178static int out_add_audio_effect(const struct audio_stream *stream __unused,
3179 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180{
3181 return 0;
3182}
3183
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003184static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3185 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186{
3187 return 0;
3188}
3189
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003190static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3191 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003193 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194}
3195
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003196static int out_get_presentation_position(const struct audio_stream_out *stream,
3197 uint64_t *frames, struct timespec *timestamp)
3198{
3199 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003200 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003201 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003202
Eric Laurenta1478072015-09-21 17:21:52 -07003203 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003204
Eric Laurent949a0892013-09-20 09:20:13 -07003205 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3206 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003207 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003208 compress_get_tstamp(out->compr, &dsp_frames,
3209 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003210 // Adjustment accounts for A2DP encoder latency with offload usecases
3211 // Note: Encoder latency is returned in ms.
3212 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3213 unsigned long offset =
3214 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3215 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3216 }
Eric Laurent949a0892013-09-20 09:20:13 -07003217 ALOGVV("%s rendered frames %ld sample_rate %d",
3218 __func__, dsp_frames, out->sample_rate);
3219 *frames = dsp_frames;
3220 ret = 0;
3221 /* this is the best we can do */
3222 clock_gettime(CLOCK_MONOTONIC, timestamp);
3223 }
3224 } else {
3225 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003226 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003227 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3228 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003229 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003230 // This adjustment accounts for buffering after app processor.
3231 // It is based on estimated DSP latency per use case, rather than exact.
3232 signed_frames -=
3233 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3234
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003235 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3236 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3237 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3238 signed_frames -=
3239 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3240 }
3241
Eric Laurent949a0892013-09-20 09:20:13 -07003242 // It would be unusual for this value to be negative, but check just in case ...
3243 if (signed_frames >= 0) {
3244 *frames = signed_frames;
3245 ret = 0;
3246 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003247 }
3248 }
3249 }
3250
3251 pthread_mutex_unlock(&out->lock);
3252
3253 return ret;
3254}
3255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256static int out_set_callback(struct audio_stream_out *stream,
3257 stream_callback_t callback, void *cookie)
3258{
3259 struct stream_out *out = (struct stream_out *)stream;
3260
3261 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003262 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003263 out->offload_callback = callback;
3264 out->offload_cookie = cookie;
3265 pthread_mutex_unlock(&out->lock);
3266 return 0;
3267}
3268
3269static int out_pause(struct audio_stream_out* stream)
3270{
3271 struct stream_out *out = (struct stream_out *)stream;
3272 int status = -ENOSYS;
3273 ALOGV("%s", __func__);
3274 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003275 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3277 status = compress_pause(out->compr);
3278 out->offload_state = OFFLOAD_STATE_PAUSED;
3279 }
3280 pthread_mutex_unlock(&out->lock);
3281 }
3282 return status;
3283}
3284
3285static int out_resume(struct audio_stream_out* stream)
3286{
3287 struct stream_out *out = (struct stream_out *)stream;
3288 int status = -ENOSYS;
3289 ALOGV("%s", __func__);
3290 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3291 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003292 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003293 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3294 status = compress_resume(out->compr);
3295 out->offload_state = OFFLOAD_STATE_PLAYING;
3296 }
3297 pthread_mutex_unlock(&out->lock);
3298 }
3299 return status;
3300}
3301
3302static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3303{
3304 struct stream_out *out = (struct stream_out *)stream;
3305 int status = -ENOSYS;
3306 ALOGV("%s", __func__);
3307 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003308 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003309 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3310 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3311 else
3312 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3313 pthread_mutex_unlock(&out->lock);
3314 }
3315 return status;
3316}
3317
3318static int out_flush(struct audio_stream_out* stream)
3319{
3320 struct stream_out *out = (struct stream_out *)stream;
3321 ALOGV("%s", __func__);
3322 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003323 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003324 stop_compressed_output_l(out);
3325 pthread_mutex_unlock(&out->lock);
3326 return 0;
3327 }
3328 return -ENOSYS;
3329}
3330
Eric Laurent0e46adf2016-12-16 12:49:24 -08003331static int out_stop(const struct audio_stream_out* stream)
3332{
3333 struct stream_out *out = (struct stream_out *)stream;
3334 struct audio_device *adev = out->dev;
3335 int ret = -ENOSYS;
3336
3337 ALOGV("%s", __func__);
3338 pthread_mutex_lock(&adev->lock);
3339 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3340 out->playback_started && out->pcm != NULL) {
3341 pcm_stop(out->pcm);
3342 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003343 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003344 }
3345 pthread_mutex_unlock(&adev->lock);
3346 return ret;
3347}
3348
3349static int out_start(const struct audio_stream_out* stream)
3350{
3351 struct stream_out *out = (struct stream_out *)stream;
3352 struct audio_device *adev = out->dev;
3353 int ret = -ENOSYS;
3354
3355 ALOGV("%s", __func__);
3356 pthread_mutex_lock(&adev->lock);
3357 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3358 !out->playback_started && out->pcm != NULL) {
3359 ret = start_output_stream(out);
3360 if (ret == 0) {
3361 out->playback_started = true;
3362 }
3363 }
3364 pthread_mutex_unlock(&adev->lock);
3365 return ret;
3366}
3367
Phil Burkbc991042017-02-24 08:06:44 -08003368/*
3369 * Modify config->period_count based on min_size_frames
3370 */
3371static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3372{
3373 int periodCountRequested = (min_size_frames + config->period_size - 1)
3374 / config->period_size;
3375 int periodCount = MMAP_PERIOD_COUNT_MIN;
3376
3377 ALOGV("%s original config.period_size = %d config.period_count = %d",
3378 __func__, config->period_size, config->period_count);
3379
3380 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3381 periodCount *= 2;
3382 }
3383 config->period_count = periodCount;
3384
3385 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3386}
3387
Eric Laurent0e46adf2016-12-16 12:49:24 -08003388static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3389 int32_t min_size_frames,
3390 struct audio_mmap_buffer_info *info)
3391{
3392 struct stream_out *out = (struct stream_out *)stream;
3393 struct audio_device *adev = out->dev;
3394 int ret = 0;
3395 unsigned int offset1;
3396 unsigned int frames1;
3397 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003398 uint32_t mmap_size;
3399 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003400
3401 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003402 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003403 pthread_mutex_lock(&adev->lock);
3404
3405 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003406 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 ret = -EINVAL;
3408 goto exit;
3409 }
3410 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003411 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003412 ret = -ENOSYS;
3413 goto exit;
3414 }
3415 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3416 if (out->pcm_device_id < 0) {
3417 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3418 __func__, out->pcm_device_id, out->usecase);
3419 ret = -EINVAL;
3420 goto exit;
3421 }
Phil Burkbc991042017-02-24 08:06:44 -08003422
3423 adjust_mmap_period_count(&out->config, min_size_frames);
3424
Eric Laurent0e46adf2016-12-16 12:49:24 -08003425 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3426 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3427 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3428 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3429 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3430 step = "open";
3431 ret = -ENODEV;
3432 goto exit;
3433 }
3434 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3435 if (ret < 0) {
3436 step = "begin";
3437 goto exit;
3438 }
3439 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003440 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003441 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003442 ret = platform_get_mmap_data_fd(adev->platform,
3443 out->pcm_device_id, 0 /*playback*/,
3444 &info->shared_memory_fd,
3445 &mmap_size);
3446 if (ret < 0) {
3447 // Fall back to non exclusive mode
3448 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3449 } else {
3450 if (mmap_size < buffer_size) {
3451 step = "mmap";
3452 goto exit;
3453 }
3454 // FIXME: indicate exclusive mode support by returning a negative buffer size
3455 info->buffer_size_frames *= -1;
3456 }
3457 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003458
3459 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3460 if (ret < 0) {
3461 step = "commit";
3462 goto exit;
3463 }
Phil Burkbc991042017-02-24 08:06:44 -08003464
3465 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003466 ret = 0;
3467
3468 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3469 __func__, info->shared_memory_address, info->buffer_size_frames);
3470
3471exit:
3472 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003473 if (out->pcm == NULL) {
3474 ALOGE("%s: %s - %d", __func__, step, ret);
3475 } else {
3476 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003477 pcm_close(out->pcm);
3478 out->pcm = NULL;
3479 }
3480 }
3481 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003482 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003483 return ret;
3484}
3485
3486static int out_get_mmap_position(const struct audio_stream_out *stream,
3487 struct audio_mmap_position *position)
3488{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003489 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003490 struct stream_out *out = (struct stream_out *)stream;
3491 ALOGVV("%s", __func__);
3492 if (position == NULL) {
3493 return -EINVAL;
3494 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003495 lock_output_stream(out);
3496 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3497 out->pcm == NULL) {
3498 ret = -ENOSYS;
3499 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003500 }
3501
3502 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003503 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003504 if (ret < 0) {
3505 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003506 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003507 }
Andy Hungfc044e12017-03-20 09:24:22 -07003508 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003509exit:
3510 pthread_mutex_unlock(&out->lock);
3511 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003512}
3513
3514
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515/** audio_stream_in implementation **/
3516static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3517{
3518 struct stream_in *in = (struct stream_in *)stream;
3519
3520 return in->config.rate;
3521}
3522
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003523static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524{
3525 return -ENOSYS;
3526}
3527
3528static size_t in_get_buffer_size(const struct audio_stream *stream)
3529{
3530 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003531 return in->config.period_size * in->af_period_multiplier *
3532 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533}
3534
3535static uint32_t in_get_channels(const struct audio_stream *stream)
3536{
3537 struct stream_in *in = (struct stream_in *)stream;
3538
3539 return in->channel_mask;
3540}
3541
vivek mehta4ed66e62016-04-15 23:33:34 -07003542static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003543{
vivek mehta4ed66e62016-04-15 23:33:34 -07003544 struct stream_in *in = (struct stream_in *)stream;
3545 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546}
3547
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003548static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003549{
3550 return -ENOSYS;
3551}
3552
3553static int in_standby(struct audio_stream *stream)
3554{
3555 struct stream_in *in = (struct stream_in *)stream;
3556 struct audio_device *adev = in->dev;
3557 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003558 bool do_stop = true;
3559
Eric Laurent994a6932013-07-17 11:51:42 -07003560 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003561
3562 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003563
3564 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003565 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003566 audio_extn_sound_trigger_stop_lab(in);
3567 in->standby = true;
3568 }
3569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003571 if (adev->adm_deregister_stream)
3572 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3573
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003574 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003576 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003577 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003578 in->capture_started = false;
3579 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003580 if (in->pcm) {
3581 pcm_close(in->pcm);
3582 in->pcm = NULL;
3583 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003584 adev->enable_voicerx = false;
3585 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003586 if (do_stop) {
3587 status = stop_input_stream(in);
3588 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003589 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003590 }
3591 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003592 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003593 return status;
3594}
3595
Andy Hungd13f0d32017-06-12 13:58:37 -07003596static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597{
Andy Hungd13f0d32017-06-12 13:58:37 -07003598 struct stream_in *in = (struct stream_in *)stream;
3599
3600 // We try to get the lock for consistency,
3601 // but it isn't necessary for these variables.
3602 // If we're not in standby, we may be blocked on a read.
3603 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3604 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3605 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3606 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3607
3608 if (locked) {
3609 pthread_mutex_unlock(&in->lock);
3610 }
3611
3612 // dump error info
3613 (void)error_log_dump(
3614 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 return 0;
3616}
3617
3618static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3619{
3620 struct stream_in *in = (struct stream_in *)stream;
3621 struct audio_device *adev = in->dev;
3622 struct str_parms *parms;
3623 char *str;
3624 char value[32];
3625 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003626 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
Eric Laurent994a6932013-07-17 11:51:42 -07003628 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 parms = str_parms_create_str(kvpairs);
3630
3631 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3632
Eric Laurenta1478072015-09-21 17:21:52 -07003633 lock_input_stream(in);
3634
Eric Laurent150dbfe2013-02-27 14:31:02 -08003635 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636 if (ret >= 0) {
3637 val = atoi(value);
3638 /* no audio source uses val == 0 */
3639 if ((in->source != val) && (val != 0)) {
3640 in->source = val;
3641 }
3642 }
3643
3644 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646 if (ret >= 0) {
3647 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003648 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003649
3650 // Workaround: If routing to an non existing usb device, fail gracefully
3651 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003652 int card;
3653 if (audio_is_usb_in_device(val) &&
3654 (card = get_alive_usb_card(parms)) >= 0) {
3655
3656 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003657 status = -ENOSYS;
3658 } else {
3659
3660 in->device = val;
3661 /* If recording is in progress, change the tx device to new device */
3662 if (!in->standby) {
3663 ALOGV("update input routing change");
3664 // inform adm before actual routing to prevent glitches.
3665 if (adev->adm_on_routing_change) {
3666 adev->adm_on_routing_change(adev->adm_data,
3667 in->capture_handle);
3668 }
3669 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003670 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003671 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003672 }
3673 }
3674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003676 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677
3678 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003679 ALOGV("%s: exit: status(%d)", __func__, status);
3680 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681}
3682
Haynes Mathew George569b7482017-05-08 14:44:27 -07003683static char* in_get_parameters(const struct audio_stream *stream,
3684 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003686 struct stream_in *in = (struct stream_in *)stream;
3687 struct str_parms *query = str_parms_create_str(keys);
3688 char *str;
3689 struct str_parms *reply = str_parms_create();
3690 bool replied = false;
3691
3692 ALOGV("%s: enter: keys - %s", __func__, keys);
3693 replied |= stream_get_parameter_channels(query, reply,
3694 &in->supported_channel_masks[0]);
3695 replied |= stream_get_parameter_formats(query, reply,
3696 &in->supported_formats[0]);
3697 replied |= stream_get_parameter_rates(query, reply,
3698 &in->supported_sample_rates[0]);
3699 if (replied) {
3700 str = str_parms_to_str(reply);
3701 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003702 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003703 }
3704 str_parms_destroy(query);
3705 str_parms_destroy(reply);
3706 ALOGV("%s: exit: returns - %s", __func__, str);
3707 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708}
3709
Eric Laurent51f3c662018-04-10 18:21:34 -07003710static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711{
Eric Laurent51f3c662018-04-10 18:21:34 -07003712 struct stream_in *in = (struct stream_in *)stream;
3713 char mixer_ctl_name[128];
3714 struct mixer_ctl *ctl;
3715 int ctl_value;
3716
3717 ALOGV("%s: gain %f", __func__, gain);
3718
3719 if (stream == NULL)
3720 return -EINVAL;
3721
3722 /* in_set_gain() only used to silence MMAP capture for now */
3723 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3724 return -ENOSYS;
3725
3726 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3727
3728 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3729 if (!ctl) {
3730 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3731 __func__, mixer_ctl_name);
3732 return -ENOSYS;
3733 }
3734
3735 if (gain < RECORD_GAIN_MIN)
3736 gain = RECORD_GAIN_MIN;
3737 else if (gain > RECORD_GAIN_MAX)
3738 gain = RECORD_GAIN_MAX;
3739 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3740
3741 mixer_ctl_set_value(ctl, 0, ctl_value);
3742 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743}
3744
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003745static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3746{
3747 if (!stream || !parms)
3748 return;
3749
3750 struct stream_in *in = (struct stream_in *)stream;
3751 struct audio_device *adev = in->dev;
3752
3753 card_status_t status;
3754 int card;
3755 if (parse_snd_card_status(parms, &card, &status) < 0)
3756 return;
3757
3758 pthread_mutex_lock(&adev->lock);
3759 bool valid_cb = (card == adev->snd_card);
3760 pthread_mutex_unlock(&adev->lock);
3761
3762 if (!valid_cb)
3763 return;
3764
3765 lock_input_stream(in);
3766 if (in->card_status != status)
3767 in->card_status = status;
3768 pthread_mutex_unlock(&in->lock);
3769
3770 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3771 use_case_table[in->usecase],
3772 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3773
3774 // a better solution would be to report error back to AF and let
3775 // it put the stream to standby
3776 if (status == CARD_STATUS_OFFLINE)
3777 in_standby(&in->stream.common);
3778
3779 return;
3780}
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3783 size_t bytes)
3784{
3785 struct stream_in *in = (struct stream_in *)stream;
3786 struct audio_device *adev = in->dev;
3787 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003788 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003789 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790
Eric Laurenta1478072015-09-21 17:21:52 -07003791 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003792 const size_t frame_size = audio_stream_in_frame_size(stream);
3793 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003794
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003795 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003797 /* Read from sound trigger HAL */
3798 audio_extn_sound_trigger_read(in, buffer, bytes);
3799 pthread_mutex_unlock(&in->lock);
3800 return bytes;
3801 }
3802
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3804 ret = -ENOSYS;
3805 goto exit;
3806 }
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003809 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003811 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 goto exit;
3814 }
3815 in->standby = 0;
3816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Andy Hungd13f0d32017-06-12 13:58:37 -07003818 // errors that occur here are read errors.
3819 error_code = ERROR_CODE_READ;
3820
Haynes Mathew George03c40102016-01-29 17:57:48 -08003821 //what's the duration requested by the client?
3822 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3823 in->config.rate;
3824 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003825
Haynes Mathew George03c40102016-01-29 17:57:48 -08003826 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003828 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003829 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003830 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003831 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003832 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003833 if (ret < 0) {
3834 ALOGE("Failed to read w/err %s", strerror(errno));
3835 ret = -errno;
3836 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003837 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3838 if (bytes % 4 == 0) {
3839 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3840 int_buf_stream = buffer;
3841 for (size_t itt=0; itt < bytes/4 ; itt++) {
3842 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003843 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003844 } else {
3845 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3846 ret = -EINVAL;
3847 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003848 }
3849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 }
3851
Haynes Mathew George03c40102016-01-29 17:57:48 -08003852 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 /*
3855 * Instead of writing zeroes here, we could trust the hardware
3856 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003857 * 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 -08003858 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003859 if (ret == 0 && adev->mic_muted &&
3860 !voice_is_in_call_rec_stream(in) &&
3861 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003863 in->frames_muted += frames;
3864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865
3866exit:
3867 pthread_mutex_unlock(&in->lock);
3868
3869 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003870 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 in_standby(&in->stream.common);
3872 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003873 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003874 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003875 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003876 }
3877 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003878 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 }
3880 return bytes;
3881}
3882
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003883static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884{
3885 return 0;
3886}
3887
Andy Hung6ebe5962016-01-15 17:46:57 -08003888static int in_get_capture_position(const struct audio_stream_in *stream,
3889 int64_t *frames, int64_t *time)
3890{
3891 if (stream == NULL || frames == NULL || time == NULL) {
3892 return -EINVAL;
3893 }
3894 struct stream_in *in = (struct stream_in *)stream;
3895 int ret = -ENOSYS;
3896
3897 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003898 // note: ST sessions do not close the alsa pcm driver synchronously
3899 // on standby. Therefore, we may return an error even though the
3900 // pcm stream is still opened.
3901 if (in->standby) {
3902 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3903 "%s stream in standby but pcm not NULL for non ST session", __func__);
3904 goto exit;
3905 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003906 if (in->pcm) {
3907 struct timespec timestamp;
3908 unsigned int avail;
3909 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3910 *frames = in->frames_read + avail;
3911 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3912 ret = 0;
3913 }
3914 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003915exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003916 pthread_mutex_unlock(&in->lock);
3917 return ret;
3918}
3919
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003920static int add_remove_audio_effect(const struct audio_stream *stream,
3921 effect_handle_t effect,
3922 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003924 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003925 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003926 int status = 0;
3927 effect_descriptor_t desc;
3928
3929 status = (*effect)->get_descriptor(effect, &desc);
3930 if (status != 0)
3931 return status;
3932
Eric Laurenta1478072015-09-21 17:21:52 -07003933 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003934 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003935 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003936 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003937 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003938 in->enable_aec != enable &&
3939 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3940 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003941 if (!enable)
3942 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003943 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3944 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3945 adev->enable_voicerx = enable;
3946 struct audio_usecase *usecase;
3947 struct listnode *node;
3948 list_for_each(node, &adev->usecase_list) {
3949 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003950 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003951 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003952 }
3953 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003954 if (!in->standby)
3955 select_devices(in->dev, in->usecase);
3956 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003957 if (in->enable_ns != enable &&
3958 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3959 in->enable_ns = enable;
3960 if (!in->standby)
3961 select_devices(in->dev, in->usecase);
3962 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003963 pthread_mutex_unlock(&in->dev->lock);
3964 pthread_mutex_unlock(&in->lock);
3965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966 return 0;
3967}
3968
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003969static int in_add_audio_effect(const struct audio_stream *stream,
3970 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971{
Eric Laurent994a6932013-07-17 11:51:42 -07003972 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003973 return add_remove_audio_effect(stream, effect, true);
3974}
3975
3976static int in_remove_audio_effect(const struct audio_stream *stream,
3977 effect_handle_t effect)
3978{
Eric Laurent994a6932013-07-17 11:51:42 -07003979 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003980 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981}
3982
Eric Laurent0e46adf2016-12-16 12:49:24 -08003983static int in_stop(const struct audio_stream_in* stream)
3984{
3985 struct stream_in *in = (struct stream_in *)stream;
3986 struct audio_device *adev = in->dev;
3987
3988 int ret = -ENOSYS;
3989 ALOGV("%s", __func__);
3990 pthread_mutex_lock(&adev->lock);
3991 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3992 in->capture_started && in->pcm != NULL) {
3993 pcm_stop(in->pcm);
3994 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003995 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003996 }
3997 pthread_mutex_unlock(&adev->lock);
3998 return ret;
3999}
4000
4001static int in_start(const struct audio_stream_in* stream)
4002{
4003 struct stream_in *in = (struct stream_in *)stream;
4004 struct audio_device *adev = in->dev;
4005 int ret = -ENOSYS;
4006
4007 ALOGV("%s in %p", __func__, in);
4008 pthread_mutex_lock(&adev->lock);
4009 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4010 !in->capture_started && in->pcm != NULL) {
4011 if (!in->capture_started) {
4012 ret = start_input_stream(in);
4013 if (ret == 0) {
4014 in->capture_started = true;
4015 }
4016 }
4017 }
4018 pthread_mutex_unlock(&adev->lock);
4019 return ret;
4020}
4021
4022static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4023 int32_t min_size_frames,
4024 struct audio_mmap_buffer_info *info)
4025{
4026 struct stream_in *in = (struct stream_in *)stream;
4027 struct audio_device *adev = in->dev;
4028 int ret = 0;
4029 unsigned int offset1;
4030 unsigned int frames1;
4031 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004032 uint32_t mmap_size;
4033 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004034
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004035 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004036 pthread_mutex_lock(&adev->lock);
4037 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004038
Eric Laurent0e46adf2016-12-16 12:49:24 -08004039 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004040 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004041 ret = -EINVAL;
4042 goto exit;
4043 }
4044 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004045 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004046 ALOGV("%s in %p", __func__, in);
4047 ret = -ENOSYS;
4048 goto exit;
4049 }
4050 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4051 if (in->pcm_device_id < 0) {
4052 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4053 __func__, in->pcm_device_id, in->usecase);
4054 ret = -EINVAL;
4055 goto exit;
4056 }
Phil Burkbc991042017-02-24 08:06:44 -08004057
4058 adjust_mmap_period_count(&in->config, min_size_frames);
4059
Eric Laurent0e46adf2016-12-16 12:49:24 -08004060 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4061 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4062 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4063 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4064 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4065 step = "open";
4066 ret = -ENODEV;
4067 goto exit;
4068 }
4069
4070 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4071 if (ret < 0) {
4072 step = "begin";
4073 goto exit;
4074 }
4075 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004076 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004077 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004078 ret = platform_get_mmap_data_fd(adev->platform,
4079 in->pcm_device_id, 1 /*capture*/,
4080 &info->shared_memory_fd,
4081 &mmap_size);
4082 if (ret < 0) {
4083 // Fall back to non exclusive mode
4084 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4085 } else {
4086 if (mmap_size < buffer_size) {
4087 step = "mmap";
4088 goto exit;
4089 }
4090 // FIXME: indicate exclusive mode support by returning a negative buffer size
4091 info->buffer_size_frames *= -1;
4092 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004093
Haynes Mathew George96483a22017-03-28 14:52:47 -07004094 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004095
4096 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4097 if (ret < 0) {
4098 step = "commit";
4099 goto exit;
4100 }
4101
Phil Burkbc991042017-02-24 08:06:44 -08004102 in->standby = false;
4103 ret = 0;
4104
Eric Laurent0e46adf2016-12-16 12:49:24 -08004105 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4106 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004107
4108exit:
4109 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004110 if (in->pcm == NULL) {
4111 ALOGE("%s: %s - %d", __func__, step, ret);
4112 } else {
4113 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004114 pcm_close(in->pcm);
4115 in->pcm = NULL;
4116 }
4117 }
4118 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004119 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004120 return ret;
4121}
4122
4123static int in_get_mmap_position(const struct audio_stream_in *stream,
4124 struct audio_mmap_position *position)
4125{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004126 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004127 struct stream_in *in = (struct stream_in *)stream;
4128 ALOGVV("%s", __func__);
4129 if (position == NULL) {
4130 return -EINVAL;
4131 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004132 lock_input_stream(in);
4133 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4134 in->pcm == NULL) {
4135 ret = -ENOSYS;
4136 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004137 }
4138 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004139 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004140 if (ret < 0) {
4141 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004142 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004143 }
Andy Hungfc044e12017-03-20 09:24:22 -07004144 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004145exit:
4146 pthread_mutex_unlock(&in->lock);
4147 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004148}
4149
jiabin8962a4d2018-03-19 18:21:24 -07004150static int in_get_active_microphones(const struct audio_stream_in *stream,
4151 struct audio_microphone_characteristic_t *mic_array,
4152 size_t *mic_count) {
4153 struct stream_in *in = (struct stream_in *)stream;
4154 struct audio_device *adev = in->dev;
4155 ALOGVV("%s", __func__);
4156
4157 lock_input_stream(in);
4158 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004159 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004160 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004161 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004162 pthread_mutex_unlock(&adev->lock);
4163 pthread_mutex_unlock(&in->lock);
4164
4165 return ret;
4166}
4167
4168static int adev_get_microphones(const struct audio_hw_device *dev,
4169 struct audio_microphone_characteristic_t *mic_array,
4170 size_t *mic_count) {
4171 struct audio_device *adev = (struct audio_device *)dev;
4172 ALOGVV("%s", __func__);
4173
4174 pthread_mutex_lock(&adev->lock);
4175 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4176 pthread_mutex_unlock(&adev->lock);
4177
4178 return ret;
4179}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004180
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181static int adev_open_output_stream(struct audio_hw_device *dev,
4182 audio_io_handle_t handle,
4183 audio_devices_t devices,
4184 audio_output_flags_t flags,
4185 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004186 struct audio_stream_out **stream_out,
4187 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188{
4189 struct audio_device *adev = (struct audio_device *)dev;
4190 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004191 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004192 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4193 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4194 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195
Andy Hungd9653bd2017-08-01 19:31:39 -07004196 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4197 return -ENOSYS;
4198 }
4199
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004200 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4201 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 *stream_out = NULL;
4203 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4204
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004205 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 if (devices == AUDIO_DEVICE_NONE)
4208 devices = AUDIO_DEVICE_OUT_SPEAKER;
4209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210 out->flags = flags;
4211 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004212 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004213 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004214 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
4216 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004217 if ((is_hdmi || is_usb_dev) &&
4218 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4219 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4220 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004221 audio_format_t req_format = config->format;
4222 audio_channel_mask_t req_channel_mask = config->channel_mask;
4223 uint32_t req_sample_rate = config->sample_rate;
4224
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004225 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004226 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004227 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004228 if (config->sample_rate == 0)
4229 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004230 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004231 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4232 if (config->format == AUDIO_FORMAT_DEFAULT)
4233 config->format = AUDIO_FORMAT_PCM_16_BIT;
4234 } else if (is_usb_dev) {
4235 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4236 &config->format,
4237 &out->supported_formats[0],
4238 MAX_SUPPORTED_FORMATS,
4239 &config->channel_mask,
4240 &out->supported_channel_masks[0],
4241 MAX_SUPPORTED_CHANNEL_MASKS,
4242 &config->sample_rate,
4243 &out->supported_sample_rates[0],
4244 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004245 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004246 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004247 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004248 if (ret != 0) {
4249 // For MMAP NO IRQ, allow conversions in ADSP
4250 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4251 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004252
Eric Laurentab805ee2018-03-30 12:20:38 -07004253 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4254 config->sample_rate = req_sample_rate;
4255 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4256 config->channel_mask = req_channel_mask;
4257 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4258 config->format = req_format;
4259 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004260
Haynes Mathew George569b7482017-05-08 14:44:27 -07004261 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004262 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004263 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004264 if (is_hdmi) {
4265 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4266 out->config = pcm_config_hdmi_multi;
4267 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4268 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4269 out->config = pcm_config_mmap_playback;
4270 out->stream.start = out_start;
4271 out->stream.stop = out_stop;
4272 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4273 out->stream.get_mmap_position = out_get_mmap_position;
4274 } else {
4275 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4276 out->config = pcm_config_hifi;
4277 }
4278
4279 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004280 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004281 if (is_hdmi) {
4282 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4283 audio_bytes_per_sample(out->format));
4284 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004285 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004286 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004287 pthread_mutex_lock(&adev->lock);
4288 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4289 pthread_mutex_unlock(&adev->lock);
4290
4291 // reject offload during card offline to allow
4292 // fallback to s/w paths
4293 if (offline) {
4294 ret = -ENODEV;
4295 goto error_open;
4296 }
4297
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004298 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4299 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4300 ALOGE("%s: Unsupported Offload information", __func__);
4301 ret = -EINVAL;
4302 goto error_open;
4303 }
4304 if (!is_supported_format(config->offload_info.format)) {
4305 ALOGE("%s: Unsupported audio format", __func__);
4306 ret = -EINVAL;
4307 goto error_open;
4308 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004309 out->sample_rate = config->offload_info.sample_rate;
4310 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4311 out->channel_mask = config->offload_info.channel_mask;
4312 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4313 out->channel_mask = config->channel_mask;
4314 else
4315 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4316
4317 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004318
4319 out->compr_config.codec = (struct snd_codec *)
4320 calloc(1, sizeof(struct snd_codec));
4321
4322 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004323
4324 out->stream.set_callback = out_set_callback;
4325 out->stream.pause = out_pause;
4326 out->stream.resume = out_resume;
4327 out->stream.drain = out_drain;
4328 out->stream.flush = out_flush;
4329
4330 out->compr_config.codec->id =
4331 get_snd_codec_id(config->offload_info.format);
4332 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4333 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004334 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004335 out->compr_config.codec->bit_rate =
4336 config->offload_info.bit_rate;
4337 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004338 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004339 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4340
4341 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4342 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004343
4344 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345 create_offload_callback_thread(out);
4346 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4347 __func__, config->offload_info.version,
4348 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004349 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4350 switch (config->sample_rate) {
4351 case 0:
4352 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4353 break;
4354 case 8000:
4355 case 16000:
4356 case 48000:
4357 out->sample_rate = config->sample_rate;
4358 break;
4359 default:
4360 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4361 config->sample_rate);
4362 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4363 ret = -EINVAL;
4364 goto error_open;
4365 }
4366 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4367 switch (config->channel_mask) {
4368 case AUDIO_CHANNEL_NONE:
4369 case AUDIO_CHANNEL_OUT_STEREO:
4370 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4371 break;
4372 default:
4373 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4374 config->channel_mask);
4375 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4376 ret = -EINVAL;
4377 goto error_open;
4378 }
4379 switch (config->format) {
4380 case AUDIO_FORMAT_DEFAULT:
4381 case AUDIO_FORMAT_PCM_16_BIT:
4382 out->format = AUDIO_FORMAT_PCM_16_BIT;
4383 break;
4384 default:
4385 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4386 config->format);
4387 config->format = AUDIO_FORMAT_PCM_16_BIT;
4388 ret = -EINVAL;
4389 goto error_open;
4390 }
4391
4392 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004393 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004394 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004395 case 0:
4396 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4397 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004398 case 8000:
4399 case 16000:
4400 case 48000:
4401 out->sample_rate = config->sample_rate;
4402 break;
4403 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004404 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4405 config->sample_rate);
4406 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4407 ret = -EINVAL;
4408 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004409 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004410 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4411 switch (config->channel_mask) {
4412 case AUDIO_CHANNEL_NONE:
4413 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4414 break;
4415 case AUDIO_CHANNEL_OUT_STEREO:
4416 out->channel_mask = config->channel_mask;
4417 break;
4418 default:
4419 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4420 config->channel_mask);
4421 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4422 ret = -EINVAL;
4423 break;
4424 }
4425 switch (config->format) {
4426 case AUDIO_FORMAT_DEFAULT:
4427 out->format = AUDIO_FORMAT_PCM_16_BIT;
4428 break;
4429 case AUDIO_FORMAT_PCM_16_BIT:
4430 out->format = config->format;
4431 break;
4432 default:
4433 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4434 config->format);
4435 config->format = AUDIO_FORMAT_PCM_16_BIT;
4436 ret = -EINVAL;
4437 break;
4438 }
4439 if (ret != 0)
4440 goto error_open;
4441
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004442 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4443 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004444 out->config.rate = out->sample_rate;
4445 out->config.channels =
4446 audio_channel_count_from_out_mask(out->channel_mask);
4447 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004448 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004449 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4450 switch (config->sample_rate) {
4451 case 0:
4452 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4453 break;
4454 case 8000:
4455 case 16000:
4456 case 32000:
4457 case 48000:
4458 out->sample_rate = config->sample_rate;
4459 break;
4460 default:
4461 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4462 config->sample_rate);
4463 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4464 ret = -EINVAL;
4465 break;
4466 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004467 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004468 switch (config->channel_mask) {
4469 case AUDIO_CHANNEL_NONE:
4470 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4471 break;
4472 case AUDIO_CHANNEL_OUT_STEREO:
4473 out->channel_mask = config->channel_mask;
4474 break;
4475 default:
4476 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4477 config->channel_mask);
4478 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4479 ret = -EINVAL;
4480 break;
4481 }
4482 switch (config->format) {
4483 case AUDIO_FORMAT_DEFAULT:
4484 out->format = AUDIO_FORMAT_PCM_16_BIT;
4485 break;
4486 case AUDIO_FORMAT_PCM_16_BIT:
4487 out->format = config->format;
4488 break;
4489 default:
4490 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4491 config->format);
4492 config->format = AUDIO_FORMAT_PCM_16_BIT;
4493 ret = -EINVAL;
4494 break;
4495 }
4496 if (ret != 0)
4497 goto error_open;
4498
vivek mehtaa68fea62017-06-08 19:04:02 -07004499 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004500 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4501 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004502 out->config.rate = out->sample_rate;
4503 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004504 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004505 out->sample_rate,
4506 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004507 out->config.channels,
4508 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004509 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004510 out->config.period_size = buffer_size / frame_size;
4511 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4512 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004514 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004515 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4516 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004517 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004518 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4519 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004520 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004521 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004522 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004523 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004524 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004525 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4526 out->config = pcm_config_mmap_playback;
4527 out->stream.start = out_start;
4528 out->stream.stop = out_stop;
4529 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4530 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004531 } else {
4532 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4533 out->config = pcm_config_low_latency;
4534 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004535
4536 if (config->sample_rate == 0) {
4537 out->sample_rate = out->config.rate;
4538 } else {
4539 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004540 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004541 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4542 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4543 } else {
4544 out->channel_mask = config->channel_mask;
4545 }
4546 if (config->format == AUDIO_FORMAT_DEFAULT)
4547 out->format = audio_format_from_pcm_format(out->config.format);
4548 else if (!audio_is_linear_pcm(config->format)) {
4549 config->format = AUDIO_FORMAT_PCM_16_BIT;
4550 ret = -EINVAL;
4551 goto error_open;
4552 } else {
4553 out->format = config->format;
4554 }
4555
4556 out->config.rate = out->sample_rate;
4557 out->config.channels =
4558 audio_channel_count_from_out_mask(out->channel_mask);
4559 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4560 out->config.format = pcm_format_from_audio_format(out->format);
4561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004563
4564 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4565 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004566 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004567 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4568 __func__, config->sample_rate, config->format, config->channel_mask);
4569 config->sample_rate = out->sample_rate;
4570 config->format = out->format;
4571 config->channel_mask = out->channel_mask;
4572 ret = -EINVAL;
4573 goto error_open;
4574 }
4575
Andy Hung6fcba9c2014-03-18 11:53:32 -07004576 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4577 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004578
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004579 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004580 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004581 adev->primary_output = out;
4582 else {
4583 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004584 ret = -EEXIST;
4585 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004586 }
4587 }
4588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 /* Check if this usecase is already existing */
4590 pthread_mutex_lock(&adev->lock);
4591 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4592 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004594 ret = -EEXIST;
4595 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596 }
4597 pthread_mutex_unlock(&adev->lock);
4598
4599 out->stream.common.get_sample_rate = out_get_sample_rate;
4600 out->stream.common.set_sample_rate = out_set_sample_rate;
4601 out->stream.common.get_buffer_size = out_get_buffer_size;
4602 out->stream.common.get_channels = out_get_channels;
4603 out->stream.common.get_format = out_get_format;
4604 out->stream.common.set_format = out_set_format;
4605 out->stream.common.standby = out_standby;
4606 out->stream.common.dump = out_dump;
4607 out->stream.common.set_parameters = out_set_parameters;
4608 out->stream.common.get_parameters = out_get_parameters;
4609 out->stream.common.add_audio_effect = out_add_audio_effect;
4610 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4611 out->stream.get_latency = out_get_latency;
4612 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004613#ifdef NO_AUDIO_OUT
4614 out->stream.write = out_write_for_no_output;
4615#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004617#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 out->stream.get_render_position = out_get_render_position;
4619 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004620 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621
Eric Laurent0e46adf2016-12-16 12:49:24 -08004622 if (out->realtime)
4623 out->af_period_multiplier = af_period_multiplier;
4624 else
4625 out->af_period_multiplier = 1;
4626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004628 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004629 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004631 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004632 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004633 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 config->format = out->stream.common.get_format(&out->stream.common);
4636 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4637 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4638
Kevin Rocarda325aa22018-04-03 09:15:52 -07004639 register_format(out->format, out->supported_formats);
4640 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4641 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4642
Andy Hunga452b0a2017-03-15 14:51:15 -07004643 out->error_log = error_log_create(
4644 ERROR_LOG_ENTRIES,
4645 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4646
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004647 /*
4648 By locking output stream before registering, we allow the callback
4649 to update stream's state only after stream's initial state is set to
4650 adev state.
4651 */
4652 lock_output_stream(out);
4653 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4654 pthread_mutex_lock(&adev->lock);
4655 out->card_status = adev->card_status;
4656 pthread_mutex_unlock(&adev->lock);
4657 pthread_mutex_unlock(&out->lock);
4658
vivek mehta4a824772017-06-08 19:05:49 -07004659 stream_app_type_cfg_init(&out->app_type_cfg);
4660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004662
Eric Laurent994a6932013-07-17 11:51:42 -07004663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004664 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004665
4666error_open:
4667 free(out);
4668 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004669 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004670 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671}
4672
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004673static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004674 struct audio_stream_out *stream)
4675{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004676 struct stream_out *out = (struct stream_out *)stream;
4677 struct audio_device *adev = out->dev;
4678
Eric Laurent994a6932013-07-17 11:51:42 -07004679 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004680
4681 // must deregister from sndmonitor first to prevent races
4682 // between the callback and close_stream
4683 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004684 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004685 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4686 destroy_offload_callback_thread(out);
4687
4688 if (out->compr_config.codec != NULL)
4689 free(out->compr_config.codec);
4690 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004691
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004692 out->a2dp_compress_mute = false;
4693
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004694 if (adev->voice_tx_output == out)
4695 adev->voice_tx_output = NULL;
4696
Andy Hunga452b0a2017-03-15 14:51:15 -07004697 error_log_destroy(out->error_log);
4698 out->error_log = NULL;
4699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004700 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004701 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004702 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004704 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004705}
4706
4707static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4708{
4709 struct audio_device *adev = (struct audio_device *)dev;
4710 struct str_parms *parms;
4711 char *str;
4712 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004713 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004715 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004716 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717
Joe Onorato188b6222016-03-01 11:02:27 -08004718 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004719
4720 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721
4722 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004723 status = voice_set_parameters(adev, parms);
4724 if (status != 0) {
4725 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726 }
4727
4728 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4729 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004730 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4732 adev->bluetooth_nrec = true;
4733 else
4734 adev->bluetooth_nrec = false;
4735 }
4736
4737 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4738 if (ret >= 0) {
4739 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4740 adev->screen_off = false;
4741 else
4742 adev->screen_off = true;
4743 }
4744
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004745 ret = str_parms_get_int(parms, "rotation", &val);
4746 if (ret >= 0) {
4747 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004748 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004749 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004750 // FIXME: note that the code below assumes that the speakers are in the correct placement
4751 // relative to the user when the device is rotated 90deg from its default rotation. This
4752 // assumption is device-specific, not platform-specific like this code.
4753 case 270:
4754 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004755 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004756 break;
4757 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004758 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07004759 camera_rotation = CAMERA_ROTATION_PORTRAIT;
4760 break;
4761 case 90:
4762 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004763 break;
4764 default:
4765 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004766 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004767 }
Eric Laurent03f09432014-03-25 18:09:11 -07004768 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004769 // check and set swap
4770 // - check if orientation changed and speaker active
4771 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07004772 adev->camera_orientation =
4773 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
4774#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07004775 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07004776#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004777 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004778 }
4779
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004780 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4781 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004782 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004783 }
4784
David Linee3fe402017-03-13 10:00:42 -07004785 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4786 if (ret >= 0) {
4787 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004788 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004789 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4790 if (ret >= 0) {
4791 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004792 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004793 }
Eric Laurent99dab492017-06-17 15:19:08 -07004794 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004795 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4796 if (ret >= 0) {
4797 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004798 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004799 }
4800 }
4801 }
4802
4803 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4804 if (ret >= 0) {
4805 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004806 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004807 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4808 if (ret >= 0) {
4809 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004810 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004811 }
Eric Laurent99dab492017-06-17 15:19:08 -07004812 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004813 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4814 if (ret >= 0) {
4815 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004816 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004817 }
4818 }
4819 }
4820
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004821 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004822 audio_extn_ma_set_parameters(adev, parms);
4823
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004824 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4825 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004826 struct audio_usecase *usecase;
4827 struct listnode *node;
4828 list_for_each(node, &adev->usecase_list) {
4829 usecase = node_to_item(node, struct audio_usecase, list);
4830 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004831 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004832 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4833
4834 pthread_mutex_unlock(&adev->lock);
4835 lock_output_stream(usecase->stream.out);
4836 pthread_mutex_lock(&adev->lock);
4837 audio_extn_a2dp_set_handoff_mode(true);
4838 // force device switch to reconfigure encoder
4839 select_devices(adev, usecase->id);
4840 audio_extn_a2dp_set_handoff_mode(false);
4841 pthread_mutex_unlock(&usecase->stream.out->lock);
4842 break;
4843 }
4844 }
4845 }
4846
Eric Laurent5f4ca952018-10-19 17:33:43 -07004847 //FIXME: to be replaced by proper video capture properties API
4848 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
4849 if (ret >= 0) {
4850 int camera_facing = CAMERA_FACING_BACK;
4851 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
4852 camera_facing = CAMERA_FACING_FRONT;
4853 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
4854 camera_facing = CAMERA_FACING_BACK;
4855 else {
4856 ALOGW("%s: invalid camera facing value: %s", __func__, value);
4857 goto done;
4858 }
4859 adev->camera_orientation =
4860 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
4861 struct audio_usecase *usecase;
4862 struct listnode *node;
4863 list_for_each(node, &adev->usecase_list) {
4864 usecase = node_to_item(node, struct audio_usecase, list);
4865 struct stream_in *in = usecase->stream.in;
4866 if (usecase->type == PCM_CAPTURE && in != NULL &&
4867 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
4868 select_devices(adev, in->usecase);
4869 }
4870 }
4871 }
4872
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004873done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004875 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004876 ALOGV("%s: exit with code(%d)", __func__, status);
4877 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004878}
4879
4880static char* adev_get_parameters(const struct audio_hw_device *dev,
4881 const char *keys)
4882{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004883 struct audio_device *adev = (struct audio_device *)dev;
4884 struct str_parms *reply = str_parms_create();
4885 struct str_parms *query = str_parms_create_str(keys);
4886 char *str;
4887
4888 pthread_mutex_lock(&adev->lock);
4889
4890 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004891 audio_extn_a2dp_get_parameters(query, reply);
4892
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004893 str = str_parms_to_str(reply);
4894 str_parms_destroy(query);
4895 str_parms_destroy(reply);
4896
4897 pthread_mutex_unlock(&adev->lock);
4898 ALOGV("%s: exit: returns - %s", __func__, str);
4899 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004900}
4901
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004902static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903{
4904 return 0;
4905}
4906
Haynes Mathew George5191a852013-09-11 14:19:36 -07004907static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4908{
4909 int ret;
4910 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004911
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004912 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4913
Haynes Mathew George5191a852013-09-11 14:19:36 -07004914 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004915 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004916 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004917
Haynes Mathew George5191a852013-09-11 14:19:36 -07004918 return ret;
4919}
4920
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004921static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922{
4923 return -ENOSYS;
4924}
4925
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004926static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4927 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928{
4929 return -ENOSYS;
4930}
4931
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004932static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933{
4934 return -ENOSYS;
4935}
4936
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004937static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938{
4939 return -ENOSYS;
4940}
4941
4942static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4943{
4944 struct audio_device *adev = (struct audio_device *)dev;
4945
4946 pthread_mutex_lock(&adev->lock);
4947 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004948 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004949 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004950 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4951 voice_is_in_call(adev)) {
4952 voice_stop_call(adev);
4953 adev->current_call_output = NULL;
4954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955 }
4956 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004957
4958 audio_extn_extspk_set_mode(adev->extspk, mode);
4959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960 return 0;
4961}
4962
4963static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4964{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004965 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967
Eric Laurent2bafff12016-03-17 12:17:23 -07004968 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004969 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004970 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4971 ret = audio_extn_hfp_set_mic_mute(adev, state);
4972 } else {
4973 ret = voice_set_mic_mute(adev, state);
4974 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004975 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004976 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004977
4978 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979}
4980
4981static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4982{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004983 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 return 0;
4985}
4986
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004987static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 const struct audio_config *config)
4989{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004990 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991
Eric Laurent74b55762017-07-09 17:04:53 -07004992 /* Don't know if USB HIFI in this context so use true to be conservative */
4993 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4994 true /*is_usb_hifi */) != 0)
4995 return 0;
4996
vivek mehtaa68fea62017-06-08 19:04:02 -07004997 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4998 config->sample_rate, config->format,
4999 channel_count,
5000 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001}
5002
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005003static bool adev_input_allow_hifi_record(struct audio_device *adev,
5004 audio_devices_t devices,
5005 audio_input_flags_t flags,
5006 audio_source_t source) {
5007 const bool allowed = true;
5008
5009 if (!audio_is_usb_in_device(devices))
5010 return !allowed;
5011
5012 switch (flags) {
5013 case AUDIO_INPUT_FLAG_NONE:
5014 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5015 break;
5016 default:
5017 return !allowed;
5018 }
5019
5020 switch (source) {
5021 case AUDIO_SOURCE_DEFAULT:
5022 case AUDIO_SOURCE_MIC:
5023 case AUDIO_SOURCE_UNPROCESSED:
5024 break;
5025 default:
5026 return !allowed;
5027 }
5028
5029 switch (adev->mode) {
5030 case 0:
5031 break;
5032 default:
5033 return !allowed;
5034 }
5035
5036 return allowed;
5037}
5038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005040 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041 audio_devices_t devices,
5042 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005043 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005044 audio_input_flags_t flags,
5045 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005046 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005047{
5048 struct audio_device *adev = (struct audio_device *)dev;
5049 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005050 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005051 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005052 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005053 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005054 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5055 devices,
5056 flags,
5057 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005058 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5059 " sample_rate %u, channel_mask %#x, format %#x",
5060 __func__, flags, is_usb_dev, may_use_hifi_record,
5061 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005062 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005063
Andy Hungd9653bd2017-08-01 19:31:39 -07005064 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5065 return -ENOSYS;
5066 }
5067
Eric Laurent74b55762017-07-09 17:04:53 -07005068 if (!(is_usb_dev && may_use_hifi_record)) {
5069 if (config->sample_rate == 0)
5070 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5071 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5072 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5073 if (config->format == AUDIO_FORMAT_DEFAULT)
5074 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005075
Eric Laurent74b55762017-07-09 17:04:53 -07005076 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5077
5078 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5079 return -EINVAL;
5080 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005082 if (audio_extn_tfa_98xx_is_supported() &&
5083 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005084 return -EINVAL;
5085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5087
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005088 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005089 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005090
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005091 in->stream.common.get_sample_rate = in_get_sample_rate;
5092 in->stream.common.set_sample_rate = in_set_sample_rate;
5093 in->stream.common.get_buffer_size = in_get_buffer_size;
5094 in->stream.common.get_channels = in_get_channels;
5095 in->stream.common.get_format = in_get_format;
5096 in->stream.common.set_format = in_set_format;
5097 in->stream.common.standby = in_standby;
5098 in->stream.common.dump = in_dump;
5099 in->stream.common.set_parameters = in_set_parameters;
5100 in->stream.common.get_parameters = in_get_parameters;
5101 in->stream.common.add_audio_effect = in_add_audio_effect;
5102 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5103 in->stream.set_gain = in_set_gain;
5104 in->stream.read = in_read;
5105 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005106 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005107 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108
5109 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005110 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005113 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005114 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115
Andy Hung88ce1d92018-10-29 18:31:12 -07005116 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005117 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5118 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5119 /* Force channel config requested to mono if incall
5120 record is being requested for only uplink/downlink */
5121 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5122 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5123 ret = -EINVAL;
5124 goto err_open;
5125 }
5126 }
5127
Haynes Mathew George569b7482017-05-08 14:44:27 -07005128 if (is_usb_dev && may_use_hifi_record) {
5129 /* HiFi record selects an appropriate format, channel, rate combo
5130 depending on sink capabilities*/
5131 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5132 &config->format,
5133 &in->supported_formats[0],
5134 MAX_SUPPORTED_FORMATS,
5135 &config->channel_mask,
5136 &in->supported_channel_masks[0],
5137 MAX_SUPPORTED_CHANNEL_MASKS,
5138 &config->sample_rate,
5139 &in->supported_sample_rates[0],
5140 MAX_SUPPORTED_SAMPLE_RATES);
5141 if (ret != 0) {
5142 ret = -EINVAL;
5143 goto err_open;
5144 }
Eric Laurent74b55762017-07-09 17:04:53 -07005145 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005146 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005147 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005148 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5149 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5150 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5151 bool ret_error = false;
5152 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5153 from HAL is 8_24
5154 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5155 8_24 return error indicating supported format is 8_24
5156 *> In case of any other source requesting 24 bit or float return error
5157 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005158
vivek mehta57ff9b52016-04-28 14:13:08 -07005159 on error flinger will retry with supported format passed
5160 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005161 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005162 config->format = AUDIO_FORMAT_PCM_16_BIT;
5163 ret_error = true;
5164 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5165 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5166 ret_error = true;
5167 }
5168
5169 if (ret_error) {
5170 ret = -EINVAL;
5171 goto err_open;
5172 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005173 }
5174
vivek mehta57ff9b52016-04-28 14:13:08 -07005175 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005176 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005179 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5180 if (config->sample_rate == 0)
5181 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5182 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5183 config->sample_rate != 8000) {
5184 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5185 ret = -EINVAL;
5186 goto err_open;
5187 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005188
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005189 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5190 config->format = AUDIO_FORMAT_PCM_16_BIT;
5191 ret = -EINVAL;
5192 goto err_open;
5193 }
5194
5195 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5196 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005197 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005198 } else if (is_usb_dev && may_use_hifi_record) {
5199 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5200 in->config = pcm_config_audio_capture;
5201 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005202 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5203 config->sample_rate,
5204 config->format,
5205 channel_count,
5206 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005207 in->config.period_size = buffer_size / frame_size;
5208 in->config.rate = config->sample_rate;
5209 in->af_period_multiplier = 1;
5210 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005211 } else {
5212 in->usecase = USECASE_AUDIO_RECORD;
5213 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005214 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005215 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005216#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005217 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005218#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005219 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005220 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005221 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005222 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005223 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5224 config->sample_rate,
5225 config->format,
5226 channel_count,
5227 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005228 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005229 in->config.rate = config->sample_rate;
5230 in->af_period_multiplier = 1;
5231 } else {
5232 // period size is left untouched for rt mode playback
5233 in->config = pcm_config_audio_capture_rt;
5234 in->af_period_multiplier = af_period_multiplier;
5235 }
5236 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5237 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005238 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005239 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5240 in->config = pcm_config_mmap_capture;
5241 in->stream.start = in_start;
5242 in->stream.stop = in_stop;
5243 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5244 in->stream.get_mmap_position = in_get_mmap_position;
5245 in->af_period_multiplier = 1;
5246 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005247 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005248 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005249 (config->sample_rate == 8000 ||
5250 config->sample_rate == 16000 ||
5251 config->sample_rate == 32000 ||
5252 config->sample_rate == 48000) &&
5253 channel_count == 1) {
5254 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5255 in->config = pcm_config_audio_capture;
5256 frame_size = audio_stream_in_frame_size(&in->stream);
5257 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5258 config->sample_rate,
5259 config->format,
5260 channel_count, false /*is_low_latency*/);
5261 in->config.period_size = buffer_size / frame_size;
5262 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5263 in->config.rate = config->sample_rate;
5264 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005265 } else {
5266 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005267 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005268 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5269 config->sample_rate,
5270 config->format,
5271 channel_count,
5272 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005273 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005274 in->config.rate = config->sample_rate;
5275 in->af_period_multiplier = 1;
5276 }
5277 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5278 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005279 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005281 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005282 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005283
Kevin Rocarda325aa22018-04-03 09:15:52 -07005284
5285 register_format(in->format, in->supported_formats);
5286 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5287 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5288
Andy Hungd13f0d32017-06-12 13:58:37 -07005289 in->error_log = error_log_create(
5290 ERROR_LOG_ENTRIES,
5291 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5292
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005293 /* This stream could be for sound trigger lab,
5294 get sound trigger pcm if present */
5295 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005297 lock_input_stream(in);
5298 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5299 pthread_mutex_lock(&adev->lock);
5300 in->card_status = adev->card_status;
5301 pthread_mutex_unlock(&adev->lock);
5302 pthread_mutex_unlock(&in->lock);
5303
vivek mehta4a824772017-06-08 19:05:49 -07005304 stream_app_type_cfg_init(&in->app_type_cfg);
5305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005307 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005308 return 0;
5309
5310err_open:
5311 free(in);
5312 *stream_in = NULL;
5313 return ret;
5314}
5315
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005316static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005317 struct audio_stream_in *stream)
5318{
Andy Hungd13f0d32017-06-12 13:58:37 -07005319 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005320 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005321
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005322 // must deregister from sndmonitor first to prevent races
5323 // between the callback and close_stream
5324 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005325 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005326
5327 error_log_destroy(in->error_log);
5328 in->error_log = NULL;
5329
Andy Hung0dbb52b2017-08-09 13:51:38 -07005330 pthread_mutex_destroy(&in->pre_lock);
5331 pthread_mutex_destroy(&in->lock);
5332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333 free(stream);
5334
5335 return;
5336}
5337
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005338static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005339{
5340 return 0;
5341}
5342
Andy Hung31aca912014-03-20 17:14:59 -07005343/* verifies input and output devices and their capabilities.
5344 *
5345 * This verification is required when enabling extended bit-depth or
5346 * sampling rates, as not all qcom products support it.
5347 *
5348 * Suitable for calling only on initialization such as adev_open().
5349 * It fills the audio_device use_case_table[] array.
5350 *
5351 * Has a side-effect that it needs to configure audio routing / devices
5352 * in order to power up the devices and read the device parameters.
5353 * It does not acquire any hw device lock. Should restore the devices
5354 * back to "normal state" upon completion.
5355 */
5356static int adev_verify_devices(struct audio_device *adev)
5357{
5358 /* enumeration is a bit difficult because one really wants to pull
5359 * the use_case, device id, etc from the hidden pcm_device_table[].
5360 * In this case there are the following use cases and device ids.
5361 *
5362 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5363 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005364 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005365 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5366 * [USECASE_AUDIO_RECORD] = {0, 0},
5367 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5368 * [USECASE_VOICE_CALL] = {2, 2},
5369 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005370 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005371 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5372 */
5373
5374 /* should be the usecases enabled in adev_open_input_stream() */
5375 static const int test_in_usecases[] = {
5376 USECASE_AUDIO_RECORD,
5377 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5378 };
5379 /* should be the usecases enabled in adev_open_output_stream()*/
5380 static const int test_out_usecases[] = {
5381 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5382 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5383 };
5384 static const usecase_type_t usecase_type_by_dir[] = {
5385 PCM_PLAYBACK,
5386 PCM_CAPTURE,
5387 };
5388 static const unsigned flags_by_dir[] = {
5389 PCM_OUT,
5390 PCM_IN,
5391 };
5392
5393 size_t i;
5394 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005395 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005396 char info[512]; /* for possible debug info */
5397
5398 for (dir = 0; dir < 2; ++dir) {
5399 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5400 const unsigned flags_dir = flags_by_dir[dir];
5401 const size_t testsize =
5402 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5403 const int *testcases =
5404 dir ? test_in_usecases : test_out_usecases;
5405 const audio_devices_t audio_device =
5406 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5407
5408 for (i = 0; i < testsize; ++i) {
5409 const audio_usecase_t audio_usecase = testcases[i];
5410 int device_id;
5411 snd_device_t snd_device;
5412 struct pcm_params **pparams;
5413 struct stream_out out;
5414 struct stream_in in;
5415 struct audio_usecase uc_info;
5416 int retval;
5417
5418 pparams = &adev->use_case_table[audio_usecase];
5419 pcm_params_free(*pparams); /* can accept null input */
5420 *pparams = NULL;
5421
5422 /* find the device ID for the use case (signed, for error) */
5423 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5424 if (device_id < 0)
5425 continue;
5426
5427 /* prepare structures for device probing */
5428 memset(&uc_info, 0, sizeof(uc_info));
5429 uc_info.id = audio_usecase;
5430 uc_info.type = usecase_type;
5431 if (dir) {
5432 adev->active_input = &in;
5433 memset(&in, 0, sizeof(in));
5434 in.device = audio_device;
5435 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5436 uc_info.stream.in = &in;
5437 } else {
5438 adev->active_input = NULL;
5439 }
5440 memset(&out, 0, sizeof(out));
5441 out.devices = audio_device; /* only field needed in select_devices */
5442 uc_info.stream.out = &out;
5443 uc_info.devices = audio_device;
5444 uc_info.in_snd_device = SND_DEVICE_NONE;
5445 uc_info.out_snd_device = SND_DEVICE_NONE;
5446 list_add_tail(&adev->usecase_list, &uc_info.list);
5447
5448 /* select device - similar to start_(in/out)put_stream() */
5449 retval = select_devices(adev, audio_usecase);
5450 if (retval >= 0) {
5451 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5452#if LOG_NDEBUG == 0
5453 if (*pparams) {
5454 ALOGV("%s: (%s) card %d device %d", __func__,
5455 dir ? "input" : "output", card_id, device_id);
5456 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005457 } else {
5458 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5459 }
5460#endif
5461 }
5462
5463 /* deselect device - similar to stop_(in/out)put_stream() */
5464 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005465 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005466 /* 2. Disable the rx device */
5467 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005468 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005469 list_remove(&uc_info.list);
5470 }
5471 }
5472 adev->active_input = NULL; /* restore adev state */
5473 return 0;
5474}
5475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476static int adev_close(hw_device_t *device)
5477{
Andy Hung31aca912014-03-20 17:14:59 -07005478 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005479 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005480
5481 if (!adev)
5482 return 0;
5483
5484 pthread_mutex_lock(&adev_init_lock);
5485
5486 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005487 audio_extn_snd_mon_unregister_listener(adev);
5488 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005489 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005490 audio_route_free(adev->audio_route);
5491 free(adev->snd_dev_ref_cnt);
5492 platform_deinit(adev->platform);
5493 audio_extn_extspk_deinit(adev->extspk);
5494 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005495 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005496 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5497 pcm_params_free(adev->use_case_table[i]);
5498 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005499 if (adev->adm_deinit)
5500 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005501 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005502 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005503 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005504
5505 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005506
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005507 return 0;
5508}
5509
Glenn Kasten4f993392014-05-14 07:30:48 -07005510/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5511 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5512 * just that it _might_ work.
5513 */
5514static int period_size_is_plausible_for_low_latency(int period_size)
5515{
5516 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005517 case 48:
5518 case 96:
5519 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005520 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005521 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005522 case 240:
5523 case 320:
5524 case 480:
5525 return 1;
5526 default:
5527 return 0;
5528 }
5529}
5530
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005531static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5532{
5533 int card;
5534 card_status_t status;
5535
5536 if (!parms)
5537 return;
5538
5539 if (parse_snd_card_status(parms, &card, &status) < 0)
5540 return;
5541
5542 pthread_mutex_lock(&adev->lock);
5543 bool valid_cb = (card == adev->snd_card);
5544 if (valid_cb) {
5545 if (adev->card_status != status) {
5546 adev->card_status = status;
5547 platform_snd_card_update(adev->platform, status);
5548 }
5549 }
5550 pthread_mutex_unlock(&adev->lock);
5551 return;
5552}
5553
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005554/* out and adev lock held */
5555static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5556{
5557 struct audio_usecase *uc_info;
5558 float left_p;
5559 float right_p;
5560 audio_devices_t devices;
5561
5562 uc_info = get_usecase_from_list(adev, out->usecase);
5563 if (uc_info == NULL) {
5564 ALOGE("%s: Could not find the usecase (%d) in the list",
5565 __func__, out->usecase);
5566 return -EINVAL;
5567 }
5568
5569 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5570 out->usecase, use_case_table[out->usecase]);
5571
5572 if (restore) {
5573 // restore A2DP device for active usecases and unmute if required
5574 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5575 !is_a2dp_device(uc_info->out_snd_device)) {
5576 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5577 select_devices(adev, uc_info->id);
5578 pthread_mutex_lock(&out->compr_mute_lock);
5579 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5580 (out->a2dp_compress_mute)) {
5581 out->a2dp_compress_mute = false;
5582 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5583 }
5584 pthread_mutex_unlock(&out->compr_mute_lock);
5585 }
5586 } else {
5587 // mute compress stream if suspended
5588 pthread_mutex_lock(&out->compr_mute_lock);
5589 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5590 (!out->a2dp_compress_mute)) {
5591 if (!out->standby) {
5592 ALOGD("%s: selecting speaker and muting stream", __func__);
5593 devices = out->devices;
5594 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5595 left_p = out->volume_l;
5596 right_p = out->volume_r;
5597 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5598 compress_pause(out->compr);
5599 set_compr_volume(&out->stream, 0.0f, 0.0f);
5600 out->a2dp_compress_mute = true;
5601 select_devices(adev, out->usecase);
5602 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5603 compress_resume(out->compr);
5604 out->devices = devices;
5605 out->volume_l = left_p;
5606 out->volume_r = right_p;
5607 }
5608 }
5609 pthread_mutex_unlock(&out->compr_mute_lock);
5610 }
5611 ALOGV("%s: exit", __func__);
5612 return 0;
5613}
5614
5615int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5616{
5617 int ret = 0;
5618
5619 lock_output_stream(out);
5620 pthread_mutex_lock(&adev->lock);
5621
5622 ret = check_a2dp_restore_l(adev, out, restore);
5623
5624 pthread_mutex_unlock(&adev->lock);
5625 pthread_mutex_unlock(&out->lock);
5626 return ret;
5627}
5628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005629static int adev_open(const hw_module_t *module, const char *name,
5630 hw_device_t **device)
5631{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005632 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005633
Eric Laurent2bafff12016-03-17 12:17:23 -07005634 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005635 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005636 pthread_mutex_lock(&adev_init_lock);
5637 if (audio_device_ref_count != 0) {
5638 *device = &adev->device.common;
5639 audio_device_ref_count++;
5640 ALOGV("%s: returning existing instance of adev", __func__);
5641 ALOGV("%s: exit", __func__);
5642 pthread_mutex_unlock(&adev_init_lock);
5643 return 0;
5644 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005645 adev = calloc(1, sizeof(struct audio_device));
5646
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005647 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005649 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5650 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5651 adev->device.common.module = (struct hw_module_t *)module;
5652 adev->device.common.close = adev_close;
5653
5654 adev->device.init_check = adev_init_check;
5655 adev->device.set_voice_volume = adev_set_voice_volume;
5656 adev->device.set_master_volume = adev_set_master_volume;
5657 adev->device.get_master_volume = adev_get_master_volume;
5658 adev->device.set_master_mute = adev_set_master_mute;
5659 adev->device.get_master_mute = adev_get_master_mute;
5660 adev->device.set_mode = adev_set_mode;
5661 adev->device.set_mic_mute = adev_set_mic_mute;
5662 adev->device.get_mic_mute = adev_get_mic_mute;
5663 adev->device.set_parameters = adev_set_parameters;
5664 adev->device.get_parameters = adev_get_parameters;
5665 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5666 adev->device.open_output_stream = adev_open_output_stream;
5667 adev->device.close_output_stream = adev_close_output_stream;
5668 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670 adev->device.close_input_stream = adev_close_input_stream;
5671 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005672 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005673
5674 /* Set the default route before the PCM stream is opened */
5675 pthread_mutex_lock(&adev->lock);
5676 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005677 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005678 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005679 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005680 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005681 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005682 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005683 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005684 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005685 pthread_mutex_unlock(&adev->lock);
5686
5687 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005688 adev->platform = platform_init(adev);
5689 if (!adev->platform) {
5690 free(adev->snd_dev_ref_cnt);
5691 free(adev);
5692 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5693 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005694 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005695 return -EINVAL;
5696 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005697 adev->extspk = audio_extn_extspk_init(adev);
5698
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005699 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5700 if (adev->visualizer_lib == NULL) {
5701 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5702 } else {
5703 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5704 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005705 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005706 "visualizer_hal_start_output");
5707 adev->visualizer_stop_output =
5708 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5709 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005710 }
5711
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005712 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5713 if (adev->offload_effects_lib == NULL) {
5714 ALOGW("%s: DLOPEN failed for %s", __func__,
5715 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5716 } else {
5717 ALOGV("%s: DLOPEN successful for %s", __func__,
5718 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5719 adev->offload_effects_start_output =
5720 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5721 "offload_effects_bundle_hal_start_output");
5722 adev->offload_effects_stop_output =
5723 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5724 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005725 }
5726
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005727 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5728 if (adev->adm_lib == NULL) {
5729 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5730 } else {
5731 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5732 adev->adm_init = (adm_init_t)
5733 dlsym(adev->adm_lib, "adm_init");
5734 adev->adm_deinit = (adm_deinit_t)
5735 dlsym(adev->adm_lib, "adm_deinit");
5736 adev->adm_register_input_stream = (adm_register_input_stream_t)
5737 dlsym(adev->adm_lib, "adm_register_input_stream");
5738 adev->adm_register_output_stream = (adm_register_output_stream_t)
5739 dlsym(adev->adm_lib, "adm_register_output_stream");
5740 adev->adm_deregister_stream = (adm_deregister_stream_t)
5741 dlsym(adev->adm_lib, "adm_deregister_stream");
5742 adev->adm_request_focus = (adm_request_focus_t)
5743 dlsym(adev->adm_lib, "adm_request_focus");
5744 adev->adm_abandon_focus = (adm_abandon_focus_t)
5745 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005746 adev->adm_set_config = (adm_set_config_t)
5747 dlsym(adev->adm_lib, "adm_set_config");
5748 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5749 dlsym(adev->adm_lib, "adm_request_focus_v2");
5750 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5751 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5752 adev->adm_on_routing_change = (adm_on_routing_change_t)
5753 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005754 }
5755
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005756 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005757 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005760
Andy Hung31aca912014-03-20 17:14:59 -07005761 if (k_enable_extended_precision)
5762 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005763
Glenn Kasten4f993392014-05-14 07:30:48 -07005764 char value[PROPERTY_VALUE_MAX];
5765 int trial;
5766 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5767 trial = atoi(value);
5768 if (period_size_is_plausible_for_low_latency(trial)) {
5769 pcm_config_low_latency.period_size = trial;
5770 pcm_config_low_latency.start_threshold = trial / 4;
5771 pcm_config_low_latency.avail_min = trial / 4;
5772 configured_low_latency_capture_period_size = trial;
5773 }
5774 }
5775 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5776 trial = atoi(value);
5777 if (period_size_is_plausible_for_low_latency(trial)) {
5778 configured_low_latency_capture_period_size = trial;
5779 }
5780 }
5781
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005782 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5783
Eric Laurent5f4ca952018-10-19 17:33:43 -07005784 adev->camera_orientation = CAMERA_DEFAULT;
5785
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005786 // commented as full set of app type cfg is sent from platform
5787 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005788 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005789
5790 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5791 af_period_multiplier = atoi(value);
5792 if (af_period_multiplier < 0) {
5793 af_period_multiplier = 2;
5794 } else if (af_period_multiplier > 4) {
5795 af_period_multiplier = 4;
5796 }
5797 ALOGV("new period_multiplier = %d", af_period_multiplier);
5798 }
5799
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005800 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005801 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005802
vivek mehta1a9b7c02015-06-25 11:49:38 -07005803 pthread_mutex_unlock(&adev_init_lock);
5804
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005805 if (adev->adm_init)
5806 adev->adm_data = adev->adm_init();
5807
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005808 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005809 audio_extn_snd_mon_init();
5810 pthread_mutex_lock(&adev->lock);
5811 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5812 adev->card_status = CARD_STATUS_ONLINE;
5813 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005814 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005815
Eric Laurent2bafff12016-03-17 12:17:23 -07005816 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817 return 0;
5818}
5819
5820static struct hw_module_methods_t hal_module_methods = {
5821 .open = adev_open,
5822};
5823
5824struct audio_module HAL_MODULE_INFO_SYM = {
5825 .common = {
5826 .tag = HARDWARE_MODULE_TAG,
5827 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5828 .hal_api_version = HARDWARE_HAL_API_VERSION,
5829 .id = AUDIO_HARDWARE_MODULE_ID,
5830 .name = "QCOM Audio HAL",
5831 .author = "Code Aurora Forum",
5832 .methods = &hal_module_methods,
5833 },
5834};