blob: 5af3897f2a83019f8e5bbdb5e51e2e830fe621bf [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
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001289struct stream_in *adev_get_active_input(const struct audio_device *adev)
1290{
1291 struct listnode *node;
1292 struct stream_in *last_active_in = NULL;
1293
1294 /* Get last added active input.
1295 * TODO: We may use a priority mechanism to pick highest priority active source */
1296 list_for_each(node, &adev->usecase_list)
1297 {
1298 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1299 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1300 last_active_in = usecase->stream.in;
1301 }
1302 }
1303
1304 return last_active_in;
1305}
1306
1307struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1308{
1309 struct listnode *node;
1310
1311 /* First check active inputs with voice communication source and then
1312 * any input if audio mode is in communication */
1313 list_for_each(node, &adev->usecase_list)
1314 {
1315 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1316 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1317 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1318 return usecase->stream.in;
1319 }
1320 }
1321 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1322 return adev_get_active_input(adev);
1323 }
1324 return NULL;
1325}
1326
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001327int select_devices(struct audio_device *adev,
1328 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001330 snd_device_t out_snd_device = SND_DEVICE_NONE;
1331 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332 struct audio_usecase *usecase = NULL;
1333 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001334 struct audio_usecase *hfp_usecase = NULL;
1335 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001336 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001338 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1339 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001341 usecase = get_usecase_from_list(adev, uc_id);
1342 if (usecase == NULL) {
1343 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1344 return -EINVAL;
1345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001347 if ((usecase->type == VOICE_CALL) ||
1348 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001349 out_snd_device = platform_get_output_snd_device(adev->platform,
1350 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001351 in_snd_device = platform_get_input_snd_device(adev->platform,
1352 NULL,
1353 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 usecase->devices = usecase->stream.out->devices;
1355 } else {
1356 /*
1357 * If the voice call is active, use the sound devices of voice call usecase
1358 * so that it would not result any device switch. All the usecases will
1359 * be switched to new device when select_devices() is called for voice call
1360 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001361 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001362 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001363 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001364 vc_usecase = get_usecase_from_list(adev,
1365 get_voice_usecase_id_from_list(adev));
1366 if ((vc_usecase != NULL) &&
1367 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1368 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369 in_snd_device = vc_usecase->in_snd_device;
1370 out_snd_device = vc_usecase->out_snd_device;
1371 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001372 } else if (audio_extn_hfp_is_active(adev)) {
1373 hfp_ucid = audio_extn_hfp_get_usecase();
1374 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1375 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1376 in_snd_device = hfp_usecase->in_snd_device;
1377 out_snd_device = hfp_usecase->out_snd_device;
1378 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 }
1380 if (usecase->type == PCM_PLAYBACK) {
1381 usecase->devices = usecase->stream.out->devices;
1382 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001383 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001384 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001385 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001386
Eric Laurentb23d5282013-05-14 15:27:20 -07001387 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001389
1390 if (voip_usecase)
1391 voip_out = voip_usecase->stream.out;
1392
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001393 if (usecase->stream.out == voip_out && voip_in != NULL) {
1394 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001395 }
1396 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001397 } else if (usecase->type == PCM_CAPTURE) {
1398 usecase->devices = usecase->stream.in->device;
1399 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001400 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001401 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001402 struct stream_in *voip_in = get_voice_communication_input(adev);
1403
1404 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001405
1406 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1407 USECASE_AUDIO_PLAYBACK_VOIP);
1408
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001409 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001410 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1411 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001412 } else if (voip_usecase) {
1413 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001414 } else if (adev->primary_output) {
1415 out_device = adev->primary_output->devices;
1416 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001417 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001418 in_snd_device = platform_get_input_snd_device(adev->platform,
1419 usecase->stream.in,
1420 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001421 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001422 }
1423 }
1424
1425 if (out_snd_device == usecase->out_snd_device &&
1426 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001427 if (!force_device_switch(usecase))
1428 return 0;
1429 }
1430
1431 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1432 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1433 return 0;
1434 }
1435
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001436 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1437 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001438 (!audio_extn_a2dp_is_ready())) {
1439 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001440 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1441 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1442 else
1443 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 }
1445
juyuchen66c4ecf2018-08-06 15:39:34 +08001446 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1447 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1448 }
1449
Eric Laurent2bafff12016-03-17 12:17:23 -07001450 if (out_snd_device != SND_DEVICE_NONE &&
1451 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1452 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1453 __func__,
1454 use_case_table[uc_id],
1455 adev->last_logged_snd_device[uc_id][0],
1456 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1457 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1458 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1459 -1,
1460 out_snd_device,
1461 platform_get_snd_device_name(out_snd_device),
1462 platform_get_snd_device_acdb_id(out_snd_device));
1463 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1464 }
1465 if (in_snd_device != SND_DEVICE_NONE &&
1466 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1467 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1468 __func__,
1469 use_case_table[uc_id],
1470 adev->last_logged_snd_device[uc_id][1],
1471 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1472 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1473 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1474 -1,
1475 in_snd_device,
1476 platform_get_snd_device_name(in_snd_device),
1477 platform_get_snd_device_acdb_id(in_snd_device));
1478 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1479 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481 /*
1482 * Limitation: While in call, to do a device switch we need to disable
1483 * and enable both RX and TX devices though one of them is same as current
1484 * device.
1485 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001486 if ((usecase->type == VOICE_CALL) &&
1487 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1488 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001489 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001490 /* Disable sidetone only if voice call already exists */
1491 if (voice_is_call_state_active(adev))
1492 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001493 }
1494
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 /* Disable current sound devices */
1496 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001497 disable_audio_route(adev, usecase);
1498 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 }
1500
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001501 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001502 disable_audio_route(adev, usecase);
1503 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504 }
1505
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001506 /* Applicable only on the targets that has external modem.
1507 * New device information should be sent to modem before enabling
1508 * the devices to reduce in-call device switch time.
1509 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001510 if ((usecase->type == VOICE_CALL) &&
1511 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1512 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001513 status = platform_switch_voice_call_enable_device_config(adev->platform,
1514 out_snd_device,
1515 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001516 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001517
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 /* Enable new sound devices */
1519 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001520 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001521 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1522 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001523 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001524 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 }
1526
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001527 if (in_snd_device != SND_DEVICE_NONE) {
1528 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001529 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531
Eric Laurentb23d5282013-05-14 15:27:20 -07001532 if (usecase->type == VOICE_CALL)
1533 status = platform_switch_voice_call_device_post(adev->platform,
1534 out_snd_device,
1535 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001536
sangwoo170731f2013-06-08 15:36:36 +09001537 usecase->in_snd_device = in_snd_device;
1538 usecase->out_snd_device = out_snd_device;
1539
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001540 audio_extn_tfa_98xx_set_mode();
1541
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001542 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001543
Jasmine Cha70771b62018-05-15 15:02:43 +08001544 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001545
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001546 /* Applicable only on the targets that has external modem.
1547 * Enable device command should be sent to modem only after
1548 * enabling voice call mixer controls
1549 */
vivek mehta765eb642015-08-07 19:46:06 -07001550 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001551 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1552 out_snd_device,
1553 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001554 /* Enable sidetone only if voice call already exists */
1555 if (voice_is_call_state_active(adev))
1556 voice_set_sidetone(adev, out_snd_device, true);
1557 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001558
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001559 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001560 struct stream_out *voip_out = voip_usecase->stream.out;
1561 audio_extn_utils_send_app_type_gain(adev,
1562 voip_out->app_type_cfg.app_type,
1563 &voip_out->app_type_cfg.gain[0]);
1564 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 return status;
1566}
1567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568static int stop_input_stream(struct stream_in *in)
1569{
1570 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 struct audio_usecase *uc_info;
1572 struct audio_device *adev = in->dev;
1573
Eric Laurent994a6932013-07-17 11:51:42 -07001574 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001576
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001577 uc_info = get_usecase_from_list(adev, in->usecase);
1578 if (uc_info == NULL) {
1579 ALOGE("%s: Could not find the usecase (%d) in the list",
1580 __func__, in->usecase);
1581 return -EINVAL;
1582 }
1583
vivek mehta781065c2017-04-04 12:55:01 -07001584 /* Close in-call recording streams */
1585 voice_check_and_stop_incall_rec_usecase(adev, in);
1586
Eric Laurent150dbfe2013-02-27 14:31:02 -08001587 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001588 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589
1590 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001591 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001593 list_remove(&uc_info->list);
1594 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595
Eric Laurent994a6932013-07-17 11:51:42 -07001596 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 return ret;
1598}
1599
1600int start_input_stream(struct stream_in *in)
1601{
1602 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001603 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 struct audio_usecase *uc_info;
1605 struct audio_device *adev = in->dev;
1606
Eric Laurent994a6932013-07-17 11:51:42 -07001607 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001608
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001609 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1610 return -EIO;
1611
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001612 if (in->card_status == CARD_STATUS_OFFLINE ||
1613 adev->card_status == CARD_STATUS_OFFLINE) {
1614 ALOGW("in->card_status or adev->card_status offline, try again");
1615 ret = -EAGAIN;
1616 goto error_config;
1617 }
1618
vivek mehta781065c2017-04-04 12:55:01 -07001619 /* Check if source matches incall recording usecase criteria */
1620 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1621 if (ret)
1622 goto error_config;
1623 else
1624 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1625
Eric Laurentb23d5282013-05-14 15:27:20 -07001626 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 if (in->pcm_device_id < 0) {
1628 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1629 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001630 ret = -EINVAL;
1631 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1635 uc_info->id = in->usecase;
1636 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001637 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001638 uc_info->devices = in->device;
1639 uc_info->in_snd_device = SND_DEVICE_NONE;
1640 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001642 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001643
Wei Wangf4837d52017-11-21 14:51:20 -08001644 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001645 audio_extn_perf_lock_acquire();
1646
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001648
Eric Laurent0e46adf2016-12-16 12:49:24 -08001649 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001650 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001651 ALOGE("%s: pcm stream not ready", __func__);
1652 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001653 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001654 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001655 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001656 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1657 goto error_open;
1658 }
1659 } else {
1660 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1661 unsigned int pcm_open_retry_count = 0;
1662
1663 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1664 flags |= PCM_MMAP | PCM_NOIRQ;
1665 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1666 } else if (in->realtime) {
1667 flags |= PCM_MMAP | PCM_NOIRQ;
1668 }
1669
1670 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1671 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1672
1673 while (1) {
1674 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1675 flags, &in->config);
1676 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1677 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1678 if (in->pcm != NULL) {
1679 pcm_close(in->pcm);
1680 in->pcm = NULL;
1681 }
1682 if (pcm_open_retry_count-- == 0) {
1683 ret = -EIO;
1684 goto error_open;
1685 }
1686 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1687 continue;
1688 }
1689 break;
1690 }
1691
1692 ALOGV("%s: pcm_prepare", __func__);
1693 ret = pcm_prepare(in->pcm);
1694 if (ret < 0) {
1695 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001696 pcm_close(in->pcm);
1697 in->pcm = NULL;
1698 goto error_open;
1699 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001700 if (in->realtime) {
1701 ret = pcm_start(in->pcm);
1702 if (ret < 0) {
1703 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1704 pcm_close(in->pcm);
1705 in->pcm = NULL;
1706 goto error_open;
1707 }
1708 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001709 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001710 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001711 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001712 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001713 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001714
Eric Laurent0e46adf2016-12-16 12:49:24 -08001715 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001716
1717error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001719 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001720 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001721
1722error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001723 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725}
1726
Eric Laurenta1478072015-09-21 17:21:52 -07001727void lock_input_stream(struct stream_in *in)
1728{
1729 pthread_mutex_lock(&in->pre_lock);
1730 pthread_mutex_lock(&in->lock);
1731 pthread_mutex_unlock(&in->pre_lock);
1732}
1733
1734void lock_output_stream(struct stream_out *out)
1735{
1736 pthread_mutex_lock(&out->pre_lock);
1737 pthread_mutex_lock(&out->lock);
1738 pthread_mutex_unlock(&out->pre_lock);
1739}
1740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741/* must be called with out->lock locked */
1742static int send_offload_cmd_l(struct stream_out* out, int command)
1743{
1744 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1745
1746 ALOGVV("%s %d", __func__, command);
1747
1748 cmd->cmd = command;
1749 list_add_tail(&out->offload_cmd_list, &cmd->node);
1750 pthread_cond_signal(&out->offload_cond);
1751 return 0;
1752}
1753
1754/* must be called iwth out->lock locked */
1755static void stop_compressed_output_l(struct stream_out *out)
1756{
1757 out->offload_state = OFFLOAD_STATE_IDLE;
1758 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001759 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 if (out->compr != NULL) {
1761 compress_stop(out->compr);
1762 while (out->offload_thread_blocked) {
1763 pthread_cond_wait(&out->cond, &out->lock);
1764 }
1765 }
1766}
1767
1768static void *offload_thread_loop(void *context)
1769{
1770 struct stream_out *out = (struct stream_out *) context;
1771 struct listnode *item;
1772
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001773 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1774 set_sched_policy(0, SP_FOREGROUND);
1775 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1776
1777 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001778
Eric Laurenta1478072015-09-21 17:21:52 -07001779 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001780 out->offload_state = OFFLOAD_STATE_IDLE;
1781 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782 for (;;) {
1783 struct offload_cmd *cmd = NULL;
1784 stream_callback_event_t event;
1785 bool send_callback = false;
1786
1787 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1788 __func__, list_empty(&out->offload_cmd_list),
1789 out->offload_state);
1790 if (list_empty(&out->offload_cmd_list)) {
1791 ALOGV("%s SLEEPING", __func__);
1792 pthread_cond_wait(&out->offload_cond, &out->lock);
1793 ALOGV("%s RUNNING", __func__);
1794 continue;
1795 }
1796
1797 item = list_head(&out->offload_cmd_list);
1798 cmd = node_to_item(item, struct offload_cmd, node);
1799 list_remove(item);
1800
1801 ALOGVV("%s STATE %d CMD %d out->compr %p",
1802 __func__, out->offload_state, cmd->cmd, out->compr);
1803
1804 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1805 free(cmd);
1806 break;
1807 }
1808
1809 if (out->compr == NULL) {
1810 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001811 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 pthread_cond_signal(&out->cond);
1813 continue;
1814 }
1815 out->offload_thread_blocked = true;
1816 pthread_mutex_unlock(&out->lock);
1817 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001818 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1820 compress_wait(out->compr, -1);
1821 send_callback = true;
1822 event = STREAM_CBK_EVENT_WRITE_READY;
1823 break;
1824 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001825 compress_next_track(out->compr);
1826 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001827 send_callback = true;
1828 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001829 /* Resend the metadata for next iteration */
1830 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001831 break;
1832 case OFFLOAD_CMD_DRAIN:
1833 compress_drain(out->compr);
1834 send_callback = true;
1835 event = STREAM_CBK_EVENT_DRAIN_READY;
1836 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001837 case OFFLOAD_CMD_ERROR:
1838 send_callback = true;
1839 event = STREAM_CBK_EVENT_ERROR;
1840 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001841 default:
1842 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1843 break;
1844 }
Eric Laurenta1478072015-09-21 17:21:52 -07001845 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001846 out->offload_thread_blocked = false;
1847 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001848 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001849 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001850 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001851 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001852 free(cmd);
1853 }
1854
1855 pthread_cond_signal(&out->cond);
1856 while (!list_empty(&out->offload_cmd_list)) {
1857 item = list_head(&out->offload_cmd_list);
1858 list_remove(item);
1859 free(node_to_item(item, struct offload_cmd, node));
1860 }
1861 pthread_mutex_unlock(&out->lock);
1862
1863 return NULL;
1864}
1865
1866static int create_offload_callback_thread(struct stream_out *out)
1867{
1868 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1869 list_init(&out->offload_cmd_list);
1870 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1871 offload_thread_loop, out);
1872 return 0;
1873}
1874
1875static int destroy_offload_callback_thread(struct stream_out *out)
1876{
Eric Laurenta1478072015-09-21 17:21:52 -07001877 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001878 stop_compressed_output_l(out);
1879 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1880
1881 pthread_mutex_unlock(&out->lock);
1882 pthread_join(out->offload_thread, (void **) NULL);
1883 pthread_cond_destroy(&out->offload_cond);
1884
1885 return 0;
1886}
1887
Eric Laurent07eeafd2013-10-06 12:52:49 -07001888static bool allow_hdmi_channel_config(struct audio_device *adev)
1889{
1890 struct listnode *node;
1891 struct audio_usecase *usecase;
1892 bool ret = true;
1893
1894 list_for_each(node, &adev->usecase_list) {
1895 usecase = node_to_item(node, struct audio_usecase, list);
1896 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1897 /*
1898 * If voice call is already existing, do not proceed further to avoid
1899 * disabling/enabling both RX and TX devices, CSD calls, etc.
1900 * Once the voice call done, the HDMI channels can be configured to
1901 * max channels of remaining use cases.
1902 */
1903 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001904 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001905 __func__);
1906 ret = false;
1907 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001908 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1909 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001910 "no change in HDMI channels", __func__);
1911 ret = false;
1912 break;
1913 }
1914 }
1915 }
1916 return ret;
1917}
1918
1919static int check_and_set_hdmi_channels(struct audio_device *adev,
1920 unsigned int channels)
1921{
1922 struct listnode *node;
1923 struct audio_usecase *usecase;
1924
1925 /* Check if change in HDMI channel config is allowed */
1926 if (!allow_hdmi_channel_config(adev))
1927 return 0;
1928
1929 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001930 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001931 return 0;
1932 }
1933
1934 platform_set_hdmi_channels(adev->platform, channels);
1935 adev->cur_hdmi_channels = channels;
1936
1937 /*
1938 * Deroute all the playback streams routed to HDMI so that
1939 * the back end is deactivated. Note that backend will not
1940 * be deactivated if any one stream is connected to it.
1941 */
1942 list_for_each(node, &adev->usecase_list) {
1943 usecase = node_to_item(node, struct audio_usecase, list);
1944 if (usecase->type == PCM_PLAYBACK &&
1945 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001946 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001947 }
1948 }
1949
1950 /*
1951 * Enable all the streams disabled above. Now the HDMI backend
1952 * will be activated with new channel configuration
1953 */
1954 list_for_each(node, &adev->usecase_list) {
1955 usecase = node_to_item(node, struct audio_usecase, list);
1956 if (usecase->type == PCM_PLAYBACK &&
1957 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001958 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001959 }
1960 }
1961
1962 return 0;
1963}
1964
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001965static int check_and_set_usb_service_interval(struct audio_device *adev,
1966 struct audio_usecase *uc_info,
1967 bool min)
1968{
1969 struct listnode *node;
1970 struct audio_usecase *usecase;
1971 bool switch_usecases = false;
1972 bool reconfig = false;
1973
1974 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1975 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1976 return -1;
1977
1978 /* set if the valid usecase do not already exist */
1979 list_for_each(node, &adev->usecase_list) {
1980 usecase = node_to_item(node, struct audio_usecase, list);
1981 if (usecase->type == PCM_PLAYBACK &&
1982 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1983 switch (usecase->id) {
1984 case USECASE_AUDIO_PLAYBACK_MMAP:
1985 case USECASE_AUDIO_PLAYBACK_ULL:
1986 // cannot reconfig while mmap/ull is present.
1987 return -1;
1988 default:
1989 switch_usecases = true;
1990 break;
1991 }
1992 }
1993 if (switch_usecases)
1994 break;
1995 }
1996 /*
1997 * client can try to set service interval in start_output_stream
1998 * to min or to 0 (i.e reset) in stop_output_stream .
1999 */
2000 unsigned long service_interval =
2001 audio_extn_usb_find_service_interval(min, true /*playback*/);
2002 int ret = platform_set_usb_service_interval(adev->platform,
2003 true /*playback*/,
2004 service_interval,
2005 &reconfig);
2006 /* no change or not supported or no active usecases */
2007 if (ret || !reconfig || !switch_usecases)
2008 return -1;
2009 return 0;
2010#undef VALID_USECASE
2011}
2012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013static int stop_output_stream(struct stream_out *out)
2014{
2015 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016 struct audio_usecase *uc_info;
2017 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002018 bool has_voip_usecase =
2019 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002020
Eric Laurent994a6932013-07-17 11:51:42 -07002021 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002022 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 uc_info = get_usecase_from_list(adev, out->usecase);
2024 if (uc_info == NULL) {
2025 ALOGE("%s: Could not find the usecase (%d) in the list",
2026 __func__, out->usecase);
2027 return -EINVAL;
2028 }
2029
Haynes Mathew George41f86652014-06-17 14:22:15 -07002030 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2031 if (adev->visualizer_stop_output != NULL)
2032 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2033 if (adev->offload_effects_stop_output != NULL)
2034 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002035 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2036 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2037 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002038 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002039
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002040 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2041 voice_set_device_mute_flag(adev, false);
2042
Eric Laurent150dbfe2013-02-27 14:31:02 -08002043 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002044 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002045
2046 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002047 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002049 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Eric Laurent0499d4f2014-08-25 22:39:29 -05002051 audio_extn_extspk_update(adev->extspk);
2052
Eric Laurent07eeafd2013-10-06 12:52:49 -07002053 /* Must be called after removing the usecase from list */
2054 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2055 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002056 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002057 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2058 if (ret == 0) {
2059 /* default service interval was successfully updated,
2060 reopen USB backend with new service interval */
2061 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2062 }
2063 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002064 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002065
HW Lee88512e92018-06-12 15:26:09 +08002066 if (has_voip_usecase ||
2067 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2068 struct listnode *node;
2069 struct audio_usecase *usecase;
2070 list_for_each(node, &adev->usecase_list) {
2071 usecase = node_to_item(node, struct audio_usecase, list);
2072 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2073 continue;
2074
2075 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2076 __func__, usecase->id, use_case_table[usecase->id],
2077 out->usecase, use_case_table[out->usecase]);
2078 select_devices(adev, usecase->id);
2079 }
2080 }
2081
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002082 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002083 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 return ret;
2085}
2086
2087int start_output_stream(struct stream_out *out)
2088{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 struct audio_usecase *uc_info;
2091 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002092 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093
Eric Laurent994a6932013-07-17 11:51:42 -07002094 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002095 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002096
2097 if (out->card_status == CARD_STATUS_OFFLINE ||
2098 adev->card_status == CARD_STATUS_OFFLINE) {
2099 ALOGW("out->card_status or adev->card_status offline, try again");
2100 ret = -EAGAIN;
2101 goto error_config;
2102 }
2103
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002104 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2105 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002106 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002107 a2dp_combo = true;
2108 } else {
2109 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2110 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2111 ret = -EAGAIN;
2112 goto error_config;
2113 }
2114 }
2115 }
2116 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002117 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 if (out->pcm_device_id < 0) {
2119 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2120 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002121 ret = -EINVAL;
2122 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 }
2124
2125 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2126 uc_info->id = out->usecase;
2127 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002128 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 uc_info->devices = out->devices;
2130 uc_info->in_snd_device = SND_DEVICE_NONE;
2131 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132
Eric Laurent07eeafd2013-10-06 12:52:49 -07002133 /* This must be called before adding this usecase to the list */
2134 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2135 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002136 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2137 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2138 /* USB backend is not reopened immediately.
2139 This is eventually done as part of select_devices */
2140 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002141
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002142 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143
Wei Wangf4837d52017-11-21 14:51:20 -08002144 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002145 audio_extn_perf_lock_acquire();
2146
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002147 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2148 (!audio_extn_a2dp_is_ready())) {
2149 if (!a2dp_combo) {
2150 check_a2dp_restore_l(adev, out, false);
2151 } else {
2152 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002153 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2154 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2155 else
2156 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002157 select_devices(adev, out->usecase);
2158 out->devices = dev;
2159 }
2160 } else {
2161 select_devices(adev, out->usecase);
2162 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163
Eric Laurent0499d4f2014-08-25 22:39:29 -05002164 audio_extn_extspk_update(adev->extspk);
2165
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002166 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2167 voice_set_device_mute_flag(adev, true);
2168
Andy Hung31aca912014-03-20 17:14:59 -07002169 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002170 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002171 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2172 out->pcm = NULL;
2173 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2174 COMPRESS_IN, &out->compr_config);
2175 if (out->compr && !is_compress_ready(out->compr)) {
2176 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2177 compress_close(out->compr);
2178 out->compr = NULL;
2179 ret = -EIO;
2180 goto error_open;
2181 }
2182 if (out->offload_callback)
2183 compress_nonblock(out->compr, out->non_blocking);
2184
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002185 if (adev->visualizer_start_output != NULL) {
2186 int capture_device_id =
2187 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2188 PCM_CAPTURE);
2189 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2190 adev->snd_card, capture_device_id);
2191 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002192 if (adev->offload_effects_start_output != NULL)
2193 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2194 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002195 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002196 ALOGE("%s: pcm stream not ready", __func__);
2197 goto error_open;
2198 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002199 ret = pcm_start(out->pcm);
2200 if (ret < 0) {
2201 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2202 goto error_open;
2203 }
2204 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002205 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002206 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002207
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002208 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2209 flags |= PCM_MMAP | PCM_NOIRQ;
2210 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002211 } else if (out->realtime) {
2212 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002213 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002214
2215 while (1) {
2216 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2217 flags, &out->config);
2218 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2219 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2220 if (out->pcm != NULL) {
2221 pcm_close(out->pcm);
2222 out->pcm = NULL;
2223 }
2224 if (pcm_open_retry_count-- == 0) {
2225 ret = -EIO;
2226 goto error_open;
2227 }
2228 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2229 continue;
2230 }
2231 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002233 ALOGV("%s: pcm_prepare", __func__);
2234 if (pcm_is_ready(out->pcm)) {
2235 ret = pcm_prepare(out->pcm);
2236 if (ret < 0) {
2237 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2238 pcm_close(out->pcm);
2239 out->pcm = NULL;
2240 goto error_open;
2241 }
2242 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002243 if (out->realtime) {
2244 ret = pcm_start(out->pcm);
2245 if (ret < 0) {
2246 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2247 pcm_close(out->pcm);
2248 out->pcm = NULL;
2249 goto error_open;
2250 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002251 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002252 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002253 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002254 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002255 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002256 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002257
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002258 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2259 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2260 audio_low_latency_hint_start();
2261 }
2262
vivek mehtae59cfb22017-06-16 15:57:11 -07002263 // consider a scenario where on pause lower layers are tear down.
2264 // so on resume, swap mixer control need to be sent only when
2265 // backend is active, hence rather than sending from enable device
2266 // sending it from start of streamtream
2267
2268 platform_set_swap_channels(adev, true);
2269
Eric Laurent994a6932013-07-17 11:51:42 -07002270 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002271 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002273 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002274 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002276error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002277 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278}
2279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280static int check_input_parameters(uint32_t sample_rate,
2281 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002282 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002284 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2285 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002286 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2287 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002288 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2289 return -EINVAL;
2290 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291
Eric Laurent74b55762017-07-09 17:04:53 -07002292 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2293 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002294 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002295 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002296 return -EINVAL;
2297 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298
2299 switch (sample_rate) {
2300 case 8000:
2301 case 11025:
2302 case 12000:
2303 case 16000:
2304 case 22050:
2305 case 24000:
2306 case 32000:
2307 case 44100:
2308 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002309 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 break;
2311 default:
vivek mehtadae44712015-07-27 14:13:18 -07002312 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002313 return -EINVAL;
2314 }
2315
2316 return 0;
2317}
2318
Kevin Rocarda325aa22018-04-03 09:15:52 -07002319/** Add a value in a list if not already present.
2320 * @return true if value was successfully inserted or already present,
2321 * false if the list is full and does not contain the value.
2322 */
2323static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2324 for (size_t i = 0; i < list_length; i++) {
2325 if (list[i] == value) return true; // value is already present
2326 if (list[i] == 0) { // no values in this slot
2327 list[i] = value;
2328 return true; // value inserted
2329 }
2330 }
2331 return false; // could not insert value
2332}
2333
2334/** Add channel_mask in supported_channel_masks if not already present.
2335 * @return true if channel_mask was successfully inserted or already present,
2336 * false if supported_channel_masks is full and does not contain channel_mask.
2337 */
2338static void register_channel_mask(audio_channel_mask_t channel_mask,
2339 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2340 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2341 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2342}
2343
2344/** Add format in supported_formats if not already present.
2345 * @return true if format was successfully inserted or already present,
2346 * false if supported_formats is full and does not contain format.
2347 */
2348static void register_format(audio_format_t format,
2349 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2350 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2351 "%s: stream can not declare supporting its format %x", __func__, format);
2352}
2353/** Add sample_rate in supported_sample_rates if not already present.
2354 * @return true if sample_rate was successfully inserted or already present,
2355 * false if supported_sample_rates is full and does not contain sample_rate.
2356 */
2357static void register_sample_rate(uint32_t sample_rate,
2358 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2359 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2360 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2361}
2362
vivek mehtaa68fea62017-06-08 19:04:02 -07002363static size_t get_stream_buffer_size(size_t duration_ms,
2364 uint32_t sample_rate,
2365 audio_format_t format,
2366 int channel_count,
2367 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368{
2369 size_t size = 0;
2370
vivek mehtaa68fea62017-06-08 19:04:02 -07002371 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002372 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002373 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002374
2375 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376
Glenn Kasten4f993392014-05-14 07:30:48 -07002377 /* make sure the size is multiple of 32 bytes
2378 * At 48 kHz mono 16-bit PCM:
2379 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2380 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2381 */
2382 size += 0x1f;
2383 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002384
2385 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386}
2387
2388static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2389{
2390 struct stream_out *out = (struct stream_out *)stream;
2391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393}
2394
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002395static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396{
2397 return -ENOSYS;
2398}
2399
2400static size_t out_get_buffer_size(const struct audio_stream *stream)
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2405 return out->compr_config.fragment_size;
2406 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002407 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002408 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002409}
2410
2411static uint32_t out_get_channels(const struct audio_stream *stream)
2412{
2413 struct stream_out *out = (struct stream_out *)stream;
2414
2415 return out->channel_mask;
2416}
2417
2418static audio_format_t out_get_format(const struct audio_stream *stream)
2419{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 struct stream_out *out = (struct stream_out *)stream;
2421
2422 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423}
2424
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002425static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426{
2427 return -ENOSYS;
2428}
2429
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002430/* must be called with out->lock locked */
2431static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 struct stream_out *out = (struct stream_out *)stream;
2434 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002435 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002438 if (adev->adm_deregister_stream)
2439 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002440 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2443 if (out->pcm) {
2444 pcm_close(out->pcm);
2445 out->pcm = NULL;
2446 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002447 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002448 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002449 out->playback_started = false;
2450 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002451 } else {
2452 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002453 out->gapless_mdata.encoder_delay = 0;
2454 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 if (out->compr != NULL) {
2456 compress_close(out->compr);
2457 out->compr = NULL;
2458 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002459 }
Phil Burkbc991042017-02-24 08:06:44 -08002460 if (do_stop) {
2461 stop_output_stream(out);
2462 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002463 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002465 return 0;
2466}
2467
2468static int out_standby(struct audio_stream *stream)
2469{
2470 struct stream_out *out = (struct stream_out *)stream;
2471
2472 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2473 out->usecase, use_case_table[out->usecase]);
2474
2475 lock_output_stream(out);
2476 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002478 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 return 0;
2480}
2481
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002482static int out_on_error(struct audio_stream *stream)
2483{
2484 struct stream_out *out = (struct stream_out *)stream;
2485 struct audio_device *adev = out->dev;
2486 bool do_standby = false;
2487
2488 lock_output_stream(out);
2489 if (!out->standby) {
2490 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2491 stop_compressed_output_l(out);
2492 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2493 } else
2494 do_standby = true;
2495 }
2496 pthread_mutex_unlock(&out->lock);
2497
2498 if (do_standby)
2499 return out_standby(&out->stream.common);
2500
2501 return 0;
2502}
2503
Andy Hung7401c7c2016-09-21 12:41:21 -07002504static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505{
Andy Hung7401c7c2016-09-21 12:41:21 -07002506 struct stream_out *out = (struct stream_out *)stream;
2507
2508 // We try to get the lock for consistency,
2509 // but it isn't necessary for these variables.
2510 // If we're not in standby, we may be blocked on a write.
2511 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2512 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2513 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2514
2515 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002516 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002517 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002518
2519 // dump error info
2520 (void)error_log_dump(
2521 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 return 0;
2524}
2525
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002526static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2527{
2528 int ret = 0;
2529 char value[32];
2530 struct compr_gapless_mdata tmp_mdata;
2531
2532 if (!out || !parms) {
2533 return -EINVAL;
2534 }
2535
2536 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2537 if (ret >= 0) {
2538 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2539 } else {
2540 return -EINVAL;
2541 }
2542
2543 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2544 if (ret >= 0) {
2545 tmp_mdata.encoder_padding = atoi(value);
2546 } else {
2547 return -EINVAL;
2548 }
2549
2550 out->gapless_mdata = tmp_mdata;
2551 out->send_new_metadata = 1;
2552 ALOGV("%s new encoder delay %u and padding %u", __func__,
2553 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2554
2555 return 0;
2556}
2557
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002558static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2559{
2560 return out == adev->primary_output || out == adev->voice_tx_output;
2561}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002562
Kevin Rocard1e02c882017-08-09 15:26:07 -07002563static int get_alive_usb_card(struct str_parms* parms) {
2564 int card;
2565 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2566 !audio_extn_usb_alive(card)) {
2567 return card;
2568 }
2569 return -ENODEV;
2570}
2571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2573{
2574 struct stream_out *out = (struct stream_out *)stream;
2575 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002576 struct audio_usecase *usecase;
2577 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 struct str_parms *parms;
2579 char value[32];
2580 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002581 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002582 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002583 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584
Eric Laurent2e140aa2016-06-30 17:14:46 -07002585 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002586 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 parms = str_parms_create_str(kvpairs);
2588 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2589 if (ret >= 0) {
2590 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002591
Eric Laurenta1478072015-09-21 17:21:52 -07002592 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002593
2594 // The usb driver needs to be closed after usb device disconnection
2595 // otherwise audio is no longer played on the new usb devices.
2596 // By forcing the stream in standby, the usb stack refcount drops to 0
2597 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002598 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002599 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002600 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2601 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2602 out_standby_l(&out->stream.common);
2603 }
2604 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002605 }
2606
Eric Laurent150dbfe2013-02-27 14:31:02 -08002607 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609 /*
2610 * When HDMI cable is unplugged the music playback is paused and
2611 * the policy manager sends routing=0. But the audioflinger
2612 * continues to write data until standby time (3sec).
2613 * As the HDMI core is turned off, the write gets blocked.
2614 * Avoid this by routing audio to speaker until standby.
2615 */
2616 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2617 val == AUDIO_DEVICE_NONE) {
2618 val = AUDIO_DEVICE_OUT_SPEAKER;
2619 }
2620
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002621 /*
2622 * When A2DP is disconnected the
2623 * music playback is paused and the policy manager sends routing=0
2624 * But the audioflingercontinues to write data until standby time
2625 * (3sec). As BT is turned off, the write gets blocked.
2626 * Avoid this by routing audio to speaker until standby.
2627 */
2628 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2629 (val == AUDIO_DEVICE_NONE) &&
2630 !audio_extn_a2dp_is_ready()) {
2631 val = AUDIO_DEVICE_OUT_SPEAKER;
2632 }
2633
2634 /* To avoid a2dp to sco overlapping / BT device improper state
2635 * check with BT lib about a2dp streaming support before routing
2636 */
2637 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2638 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002639 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002640 //combo usecase just by pass a2dp
2641 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2642 bypass_a2dp = true;
2643 } else {
2644 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2645 /* update device to a2dp and don't route as BT returned error
2646 * However it is still possible a2dp routing called because
2647 * of current active device disconnection (like wired headset)
2648 */
2649 out->devices = val;
2650 pthread_mutex_unlock(&out->lock);
2651 pthread_mutex_unlock(&adev->lock);
2652 status = -ENOSYS;
2653 goto routing_fail;
2654 }
2655 }
2656 }
2657
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002658 audio_devices_t new_dev = val;
2659
2660 // Workaround: If routing to an non existing usb device, fail gracefully
2661 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002662 int card;
2663 if (audio_is_usb_out_device(new_dev) &&
2664 (card = get_alive_usb_card(parms)) >= 0) {
2665
2666 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002667 pthread_mutex_unlock(&adev->lock);
2668 pthread_mutex_unlock(&out->lock);
2669 status = -ENOSYS;
2670 goto routing_fail;
2671 }
2672
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002673 /*
2674 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002675 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 * the select_devices(). But how do we undo this?
2677 *
2678 * For example, music playback is active on headset (deep-buffer usecase)
2679 * and if we go to ringtones and select a ringtone, low-latency usecase
2680 * will be started on headset+speaker. As we can't enable headset+speaker
2681 * and headset devices at the same time, select_devices() switches the music
2682 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2683 * So when the ringtone playback is completed, how do we undo the same?
2684 *
2685 * We are relying on the out_set_parameters() call on deep-buffer output,
2686 * once the ringtone playback is ended.
2687 * NOTE: We should not check if the current devices are same as new devices.
2688 * Because select_devices() must be called to switch back the music
2689 * playback to headset.
2690 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002691 if (new_dev != AUDIO_DEVICE_NONE) {
2692 bool same_dev = out->devices == new_dev;
2693 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002694
Eric Laurenta7657192014-10-09 21:09:33 -07002695 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002696 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002697 if (adev->mode == AUDIO_MODE_IN_CALL) {
2698 adev->current_call_output = out;
2699 ret = voice_start_call(adev);
2700 }
2701 } else {
2702 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002703 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002704 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002705 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002706
2707 if (!out->standby) {
2708 if (!same_dev) {
2709 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002710 // inform adm before actual routing to prevent glitches.
2711 if (adev->adm_on_routing_change) {
2712 adev->adm_on_routing_change(adev->adm_data,
2713 out->handle);
2714 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002715 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002716 if (!bypass_a2dp) {
2717 select_devices(adev, out->usecase);
2718 } else {
juyuchen9baad392018-06-05 19:02:10 +08002719 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2720 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2721 else
2722 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002723 select_devices(adev, out->usecase);
2724 out->devices = new_dev;
2725 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002726 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002727
2728 // on device switch force swap, lower functions will make sure
2729 // to check if swap is allowed or not.
2730
2731 if (!same_dev)
2732 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002733
2734 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2735 out->a2dp_compress_mute &&
2736 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2737 pthread_mutex_lock(&out->compr_mute_lock);
2738 out->a2dp_compress_mute = false;
2739 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2740 pthread_mutex_unlock(&out->compr_mute_lock);
2741 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002742 }
2743
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002744 }
2745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002747 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002748
2749 /*handles device and call state changes*/
2750 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002752 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002753
2754 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2755 parse_compress_metadata(out, parms);
2756 }
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002759 ALOGV("%s: exit: code(%d)", __func__, status);
2760 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761}
2762
Haynes Mathew George569b7482017-05-08 14:44:27 -07002763static bool stream_get_parameter_channels(struct str_parms *query,
2764 struct str_parms *reply,
2765 audio_channel_mask_t *supported_channel_masks) {
2766 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002767 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002769 size_t i, j;
2770
2771 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2772 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773 value[0] = '\0';
2774 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002775 while (supported_channel_masks[i] != 0) {
2776 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2777 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 if (!first) {
2779 strcat(value, "|");
2780 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002781 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 first = false;
2783 break;
2784 }
2785 }
2786 i++;
2787 }
2788 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002789 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002790 return ret >= 0;
2791}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002792
Haynes Mathew George569b7482017-05-08 14:44:27 -07002793static bool stream_get_parameter_formats(struct str_parms *query,
2794 struct str_parms *reply,
2795 audio_format_t *supported_formats) {
2796 int ret = -1;
2797 char value[256];
2798 int i;
2799
2800 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2801 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002802 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002803 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002804 case AUDIO_FORMAT_PCM_16_BIT:
2805 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2806 break;
2807 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2808 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2809 break;
2810 case AUDIO_FORMAT_PCM_32_BIT:
2811 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2812 break;
2813 default:
2814 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002815 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002816 break;
2817 }
2818 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002819 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002820 return ret >= 0;
2821}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002822
Haynes Mathew George569b7482017-05-08 14:44:27 -07002823static bool stream_get_parameter_rates(struct str_parms *query,
2824 struct str_parms *reply,
2825 uint32_t *supported_sample_rates) {
2826
2827 int i;
2828 char value[256];
2829 int ret = -1;
2830 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2831 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002832 value[0] = '\0';
2833 i=0;
2834 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002835 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002836 int avail = sizeof(value) - cursor;
2837 ret = snprintf(value + cursor, avail, "%s%d",
2838 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002839 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002840 if (ret < 0 || ret >= avail) {
2841 // if cursor is at the last element of the array
2842 // overwrite with \0 is duplicate work as
2843 // snprintf already put a \0 in place.
2844 // else
2845 // we had space to write the '|' at value[cursor]
2846 // (which will be overwritten) or no space to fill
2847 // the first element (=> cursor == 0)
2848 value[cursor] = '\0';
2849 break;
2850 }
2851 cursor += ret;
2852 ++i;
2853 }
2854 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2855 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002856 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002857 return ret >= 0;
2858}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002859
Haynes Mathew George569b7482017-05-08 14:44:27 -07002860static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2861{
2862 struct stream_out *out = (struct stream_out *)stream;
2863 struct str_parms *query = str_parms_create_str(keys);
2864 char *str;
2865 struct str_parms *reply = str_parms_create();
2866 bool replied = false;
2867 ALOGV("%s: enter: keys - %s", __func__, keys);
2868
2869 replied |= stream_get_parameter_channels(query, reply,
2870 &out->supported_channel_masks[0]);
2871 replied |= stream_get_parameter_formats(query, reply,
2872 &out->supported_formats[0]);
2873 replied |= stream_get_parameter_rates(query, reply,
2874 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002875 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 str = str_parms_to_str(reply);
2877 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002878 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 }
2880 str_parms_destroy(query);
2881 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002882 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 return str;
2884}
2885
2886static uint32_t out_get_latency(const struct audio_stream_out *stream)
2887{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002888 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002890 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2893 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002894 else if ((out->realtime) ||
2895 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002896 // since the buffer won't be filled up faster than realtime,
2897 // return a smaller number
2898 period_ms = (out->af_period_multiplier * out->config.period_size *
2899 1000) / (out->config.rate);
2900 hw_delay = platform_render_latency(out->usecase)/1000;
2901 return period_ms + hw_delay;
2902 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002904 latency = (out->config.period_count * out->config.period_size * 1000) /
2905 (out->config.rate);
2906
2907 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2908 latency += audio_extn_a2dp_get_encoder_latency();
2909
2910 return latency;
2911}
2912
2913static int set_compr_volume(struct audio_stream_out *stream, float left,
2914 float right)
2915{
2916 struct stream_out *out = (struct stream_out *)stream;
2917 int volume[2];
2918 char mixer_ctl_name[128];
2919 struct audio_device *adev = out->dev;
2920 struct mixer_ctl *ctl;
2921 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2922 PCM_PLAYBACK);
2923
2924 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2925 "Compress Playback %d Volume", pcm_device_id);
2926 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2927 if (!ctl) {
2928 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2929 __func__, mixer_ctl_name);
2930 return -EINVAL;
2931 }
2932 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2933 __func__, mixer_ctl_name, left, right);
2934 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2935 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2936 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2937
2938 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939}
2940
2941static int out_set_volume(struct audio_stream_out *stream, float left,
2942 float right)
2943{
Eric Laurenta9024de2013-04-04 09:19:12 -07002944 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002945 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002947 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002948 /* only take left channel into account: the API is for stereo anyway */
2949 out->muted = (left == 0.0f);
2950 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002951 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002952 pthread_mutex_lock(&out->compr_mute_lock);
2953 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2954 if (!out->a2dp_compress_mute)
2955 ret = set_compr_volume(stream, left, right);
2956 out->volume_l = left;
2957 out->volume_r = right;
2958 pthread_mutex_unlock(&out->compr_mute_lock);
2959 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002960 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002961 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2962 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2963 if (!out->standby) {
2964 // if in standby, cached volume will be sent after stream is opened
2965 audio_extn_utils_send_app_type_gain(out->dev,
2966 out->app_type_cfg.app_type,
2967 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002968 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002969 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002970 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972 return -ENOSYS;
2973}
2974
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002975// note: this call is safe only if the stream_cb is
2976// removed first in close_output_stream (as is done now).
2977static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2978{
2979 if (!stream || !parms)
2980 return;
2981
2982 struct stream_out *out = (struct stream_out *)stream;
2983 struct audio_device *adev = out->dev;
2984
2985 card_status_t status;
2986 int card;
2987 if (parse_snd_card_status(parms, &card, &status) < 0)
2988 return;
2989
2990 pthread_mutex_lock(&adev->lock);
2991 bool valid_cb = (card == adev->snd_card);
2992 pthread_mutex_unlock(&adev->lock);
2993
2994 if (!valid_cb)
2995 return;
2996
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002997 lock_output_stream(out);
2998 if (out->card_status != status)
2999 out->card_status = status;
3000 pthread_mutex_unlock(&out->lock);
3001
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003002 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3003 use_case_table[out->usecase],
3004 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3005
3006 if (status == CARD_STATUS_OFFLINE)
3007 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003008
3009 return;
3010}
3011
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003012#ifdef NO_AUDIO_OUT
3013static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003014 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003015{
3016 struct stream_out *out = (struct stream_out *)stream;
3017
3018 /* No Output device supported other than BT for playback.
3019 * Sleep for the amount of buffer duration
3020 */
Eric Laurenta1478072015-09-21 17:21:52 -07003021 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003022 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3023 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003024 out_get_sample_rate(&out->stream.common));
3025 pthread_mutex_unlock(&out->lock);
3026 return bytes;
3027}
3028#endif
3029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3031 size_t bytes)
3032{
3033 struct stream_out *out = (struct stream_out *)stream;
3034 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003035 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003036 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037
Eric Laurenta1478072015-09-21 17:21:52 -07003038 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003039 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003040 const size_t frame_size = audio_stream_out_frame_size(stream);
3041 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003042
Eric Laurent0e46adf2016-12-16 12:49:24 -08003043 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3044 error_code = ERROR_CODE_WRITE;
3045 goto exit;
3046 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003047
3048 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3049 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003050 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003051 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3052 ret = -EIO;
3053 goto exit;
3054 }
3055 }
3056 }
3057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003059 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003060 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003062
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003063 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003065 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003066 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067 goto exit;
3068 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003069
vivek mehta40125092017-08-21 18:48:51 -07003070 // after standby always force set last known cal step
3071 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3072 ALOGD("%s: retry previous failed cal level set", __func__);
3073 send_gain_dep_calibration_l();
3074 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003078 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003079 if (out->send_new_metadata) {
3080 ALOGVV("send new gapless metadata");
3081 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3082 out->send_new_metadata = 0;
3083 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003084 unsigned int avail;
3085 struct timespec tstamp;
3086 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3087 /* Do not limit write size if the available frames count is unknown */
3088 if (ret != 0) {
3089 avail = bytes;
3090 }
3091 if (avail == 0) {
3092 ret = 0;
3093 } else {
3094 if (avail > bytes) {
3095 avail = bytes;
3096 }
3097 ret = compress_write(out->compr, buffer, avail);
3098 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3099 __func__, avail, ret);
3100 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003101
Eric Laurent6e895242013-09-05 16:10:57 -07003102 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3104 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003105 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003106 compress_start(out->compr);
3107 out->playback_started = 1;
3108 out->offload_state = OFFLOAD_STATE_PLAYING;
3109 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003110 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003111 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003112 } else {
3113 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003114 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003115 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003116 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 return ret;
3118 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003119 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003121 size_t bytes_to_write = bytes;
3122
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003123 if (out->muted)
3124 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003125 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003126 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003127 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3128 int16_t *src = (int16_t *)buffer;
3129 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003130
Eric Laurentad2dde92017-09-20 18:27:31 -07003131 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3132 out->format != AUDIO_FORMAT_PCM_16_BIT,
3133 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003134
Eric Laurentad2dde92017-09-20 18:27:31 -07003135 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3136 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3137 }
3138 bytes_to_write /= 2;
3139 }
3140 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3141
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003142 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003143 request_out_focus(out, ns);
3144
3145 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3146 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003147 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003148 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003149 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003150
Haynes Mathew George03c40102016-01-29 17:57:48 -08003151 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003152 } else {
3153 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003154 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 }
3156
3157exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003158 // For PCM we always consume the buffer and return #bytes regardless of ret.
3159 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003160 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003161 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003162 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003163
Andy Hung7401c7c2016-09-21 12:41:21 -07003164 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003165 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003166 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3167 ALOGE_IF(out->pcm != NULL,
3168 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003169 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003170 // usleep not guaranteed for values over 1 second but we don't limit here.
3171 }
3172 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 pthread_mutex_unlock(&out->lock);
3175
3176 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003177 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003178 if (sleeptime_us != 0)
3179 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 }
3181 return bytes;
3182}
3183
3184static int out_get_render_position(const struct audio_stream_out *stream,
3185 uint32_t *dsp_frames)
3186{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003187 struct stream_out *out = (struct stream_out *)stream;
3188 *dsp_frames = 0;
3189 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003190 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003192 unsigned long frames = 0;
3193 // TODO: check return value
3194 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3195 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003196 ALOGVV("%s rendered frames %d sample_rate %d",
3197 __func__, *dsp_frames, out->sample_rate);
3198 }
3199 pthread_mutex_unlock(&out->lock);
3200 return 0;
3201 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003202 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203}
3204
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003205static int out_add_audio_effect(const struct audio_stream *stream __unused,
3206 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207{
3208 return 0;
3209}
3210
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003211static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3212 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213{
3214 return 0;
3215}
3216
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003217static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3218 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003220 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003223static int out_get_presentation_position(const struct audio_stream_out *stream,
3224 uint64_t *frames, struct timespec *timestamp)
3225{
3226 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003227 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003228 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003229
Eric Laurenta1478072015-09-21 17:21:52 -07003230 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003231
Eric Laurent949a0892013-09-20 09:20:13 -07003232 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3233 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003234 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003235 compress_get_tstamp(out->compr, &dsp_frames,
3236 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003237 // Adjustment accounts for A2DP encoder latency with offload usecases
3238 // Note: Encoder latency is returned in ms.
3239 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3240 unsigned long offset =
3241 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3242 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3243 }
Eric Laurent949a0892013-09-20 09:20:13 -07003244 ALOGVV("%s rendered frames %ld sample_rate %d",
3245 __func__, dsp_frames, out->sample_rate);
3246 *frames = dsp_frames;
3247 ret = 0;
3248 /* this is the best we can do */
3249 clock_gettime(CLOCK_MONOTONIC, timestamp);
3250 }
3251 } else {
3252 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003253 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003254 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3255 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003256 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003257 // This adjustment accounts for buffering after app processor.
3258 // It is based on estimated DSP latency per use case, rather than exact.
3259 signed_frames -=
3260 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3261
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003262 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3263 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3264 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3265 signed_frames -=
3266 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3267 }
3268
Eric Laurent949a0892013-09-20 09:20:13 -07003269 // It would be unusual for this value to be negative, but check just in case ...
3270 if (signed_frames >= 0) {
3271 *frames = signed_frames;
3272 ret = 0;
3273 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003274 }
3275 }
3276 }
3277
3278 pthread_mutex_unlock(&out->lock);
3279
3280 return ret;
3281}
3282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003283static int out_set_callback(struct audio_stream_out *stream,
3284 stream_callback_t callback, void *cookie)
3285{
3286 struct stream_out *out = (struct stream_out *)stream;
3287
3288 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003289 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 out->offload_callback = callback;
3291 out->offload_cookie = cookie;
3292 pthread_mutex_unlock(&out->lock);
3293 return 0;
3294}
3295
3296static int out_pause(struct audio_stream_out* stream)
3297{
3298 struct stream_out *out = (struct stream_out *)stream;
3299 int status = -ENOSYS;
3300 ALOGV("%s", __func__);
3301 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003302 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003303 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3304 status = compress_pause(out->compr);
3305 out->offload_state = OFFLOAD_STATE_PAUSED;
3306 }
3307 pthread_mutex_unlock(&out->lock);
3308 }
3309 return status;
3310}
3311
3312static int out_resume(struct audio_stream_out* stream)
3313{
3314 struct stream_out *out = (struct stream_out *)stream;
3315 int status = -ENOSYS;
3316 ALOGV("%s", __func__);
3317 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3318 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003319 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003320 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3321 status = compress_resume(out->compr);
3322 out->offload_state = OFFLOAD_STATE_PLAYING;
3323 }
3324 pthread_mutex_unlock(&out->lock);
3325 }
3326 return status;
3327}
3328
3329static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3330{
3331 struct stream_out *out = (struct stream_out *)stream;
3332 int status = -ENOSYS;
3333 ALOGV("%s", __func__);
3334 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003335 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003336 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3337 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3338 else
3339 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3340 pthread_mutex_unlock(&out->lock);
3341 }
3342 return status;
3343}
3344
3345static int out_flush(struct audio_stream_out* stream)
3346{
3347 struct stream_out *out = (struct stream_out *)stream;
3348 ALOGV("%s", __func__);
3349 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003350 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351 stop_compressed_output_l(out);
3352 pthread_mutex_unlock(&out->lock);
3353 return 0;
3354 }
3355 return -ENOSYS;
3356}
3357
Eric Laurent0e46adf2016-12-16 12:49:24 -08003358static int out_stop(const struct audio_stream_out* stream)
3359{
3360 struct stream_out *out = (struct stream_out *)stream;
3361 struct audio_device *adev = out->dev;
3362 int ret = -ENOSYS;
3363
3364 ALOGV("%s", __func__);
3365 pthread_mutex_lock(&adev->lock);
3366 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3367 out->playback_started && out->pcm != NULL) {
3368 pcm_stop(out->pcm);
3369 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003370 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003371 }
3372 pthread_mutex_unlock(&adev->lock);
3373 return ret;
3374}
3375
3376static int out_start(const struct audio_stream_out* stream)
3377{
3378 struct stream_out *out = (struct stream_out *)stream;
3379 struct audio_device *adev = out->dev;
3380 int ret = -ENOSYS;
3381
3382 ALOGV("%s", __func__);
3383 pthread_mutex_lock(&adev->lock);
3384 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3385 !out->playback_started && out->pcm != NULL) {
3386 ret = start_output_stream(out);
3387 if (ret == 0) {
3388 out->playback_started = true;
3389 }
3390 }
3391 pthread_mutex_unlock(&adev->lock);
3392 return ret;
3393}
3394
Phil Burkbc991042017-02-24 08:06:44 -08003395/*
3396 * Modify config->period_count based on min_size_frames
3397 */
3398static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3399{
3400 int periodCountRequested = (min_size_frames + config->period_size - 1)
3401 / config->period_size;
3402 int periodCount = MMAP_PERIOD_COUNT_MIN;
3403
3404 ALOGV("%s original config.period_size = %d config.period_count = %d",
3405 __func__, config->period_size, config->period_count);
3406
3407 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3408 periodCount *= 2;
3409 }
3410 config->period_count = periodCount;
3411
3412 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3413}
3414
Eric Laurent0e46adf2016-12-16 12:49:24 -08003415static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3416 int32_t min_size_frames,
3417 struct audio_mmap_buffer_info *info)
3418{
3419 struct stream_out *out = (struct stream_out *)stream;
3420 struct audio_device *adev = out->dev;
3421 int ret = 0;
3422 unsigned int offset1;
3423 unsigned int frames1;
3424 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003425 uint32_t mmap_size;
3426 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003427
3428 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003429 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003430 pthread_mutex_lock(&adev->lock);
3431
3432 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003433 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003434 ret = -EINVAL;
3435 goto exit;
3436 }
3437 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003438 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003439 ret = -ENOSYS;
3440 goto exit;
3441 }
3442 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3443 if (out->pcm_device_id < 0) {
3444 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3445 __func__, out->pcm_device_id, out->usecase);
3446 ret = -EINVAL;
3447 goto exit;
3448 }
Phil Burkbc991042017-02-24 08:06:44 -08003449
3450 adjust_mmap_period_count(&out->config, min_size_frames);
3451
Eric Laurent0e46adf2016-12-16 12:49:24 -08003452 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3453 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3454 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3455 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3456 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3457 step = "open";
3458 ret = -ENODEV;
3459 goto exit;
3460 }
3461 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3462 if (ret < 0) {
3463 step = "begin";
3464 goto exit;
3465 }
3466 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003467 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003468 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003469 ret = platform_get_mmap_data_fd(adev->platform,
3470 out->pcm_device_id, 0 /*playback*/,
3471 &info->shared_memory_fd,
3472 &mmap_size);
3473 if (ret < 0) {
3474 // Fall back to non exclusive mode
3475 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3476 } else {
3477 if (mmap_size < buffer_size) {
3478 step = "mmap";
3479 goto exit;
3480 }
3481 // FIXME: indicate exclusive mode support by returning a negative buffer size
3482 info->buffer_size_frames *= -1;
3483 }
3484 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003485
3486 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3487 if (ret < 0) {
3488 step = "commit";
3489 goto exit;
3490 }
Phil Burkbc991042017-02-24 08:06:44 -08003491
3492 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003493 ret = 0;
3494
3495 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3496 __func__, info->shared_memory_address, info->buffer_size_frames);
3497
3498exit:
3499 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003500 if (out->pcm == NULL) {
3501 ALOGE("%s: %s - %d", __func__, step, ret);
3502 } else {
3503 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003504 pcm_close(out->pcm);
3505 out->pcm = NULL;
3506 }
3507 }
3508 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003509 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003510 return ret;
3511}
3512
3513static int out_get_mmap_position(const struct audio_stream_out *stream,
3514 struct audio_mmap_position *position)
3515{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003516 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003517 struct stream_out *out = (struct stream_out *)stream;
3518 ALOGVV("%s", __func__);
3519 if (position == NULL) {
3520 return -EINVAL;
3521 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003522 lock_output_stream(out);
3523 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3524 out->pcm == NULL) {
3525 ret = -ENOSYS;
3526 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003527 }
3528
3529 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003530 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003531 if (ret < 0) {
3532 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003533 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003534 }
Andy Hungfc044e12017-03-20 09:24:22 -07003535 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003536exit:
3537 pthread_mutex_unlock(&out->lock);
3538 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003539}
3540
3541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542/** audio_stream_in implementation **/
3543static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3544{
3545 struct stream_in *in = (struct stream_in *)stream;
3546
3547 return in->config.rate;
3548}
3549
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003550static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003551{
3552 return -ENOSYS;
3553}
3554
3555static size_t in_get_buffer_size(const struct audio_stream *stream)
3556{
3557 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003558 return in->config.period_size * in->af_period_multiplier *
3559 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560}
3561
3562static uint32_t in_get_channels(const struct audio_stream *stream)
3563{
3564 struct stream_in *in = (struct stream_in *)stream;
3565
3566 return in->channel_mask;
3567}
3568
vivek mehta4ed66e62016-04-15 23:33:34 -07003569static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570{
vivek mehta4ed66e62016-04-15 23:33:34 -07003571 struct stream_in *in = (struct stream_in *)stream;
3572 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573}
3574
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003575static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576{
3577 return -ENOSYS;
3578}
3579
3580static int in_standby(struct audio_stream *stream)
3581{
3582 struct stream_in *in = (struct stream_in *)stream;
3583 struct audio_device *adev = in->dev;
3584 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003585 bool do_stop = true;
3586
Eric Laurent994a6932013-07-17 11:51:42 -07003587 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003588
3589 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003590
3591 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003592 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003593 audio_extn_sound_trigger_stop_lab(in);
3594 in->standby = true;
3595 }
3596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003598 if (adev->adm_deregister_stream)
3599 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3600
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003601 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003604 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003605 in->capture_started = false;
3606 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003607 if (in->pcm) {
3608 pcm_close(in->pcm);
3609 in->pcm = NULL;
3610 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003611 adev->enable_voicerx = false;
3612 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003613 if (do_stop) {
3614 status = stop_input_stream(in);
3615 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003616 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 }
3618 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003619 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003620 return status;
3621}
3622
Andy Hungd13f0d32017-06-12 13:58:37 -07003623static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624{
Andy Hungd13f0d32017-06-12 13:58:37 -07003625 struct stream_in *in = (struct stream_in *)stream;
3626
3627 // We try to get the lock for consistency,
3628 // but it isn't necessary for these variables.
3629 // If we're not in standby, we may be blocked on a read.
3630 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3631 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3632 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3633 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3634
3635 if (locked) {
3636 pthread_mutex_unlock(&in->lock);
3637 }
3638
3639 // dump error info
3640 (void)error_log_dump(
3641 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 return 0;
3643}
3644
3645static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3646{
3647 struct stream_in *in = (struct stream_in *)stream;
3648 struct audio_device *adev = in->dev;
3649 struct str_parms *parms;
3650 char *str;
3651 char value[32];
3652 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003653 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654
Eric Laurent994a6932013-07-17 11:51:42 -07003655 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656 parms = str_parms_create_str(kvpairs);
3657
3658 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3659
Eric Laurenta1478072015-09-21 17:21:52 -07003660 lock_input_stream(in);
3661
Eric Laurent150dbfe2013-02-27 14:31:02 -08003662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663 if (ret >= 0) {
3664 val = atoi(value);
3665 /* no audio source uses val == 0 */
3666 if ((in->source != val) && (val != 0)) {
3667 in->source = val;
3668 }
3669 }
3670
3671 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003672
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 if (ret >= 0) {
3674 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003675 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003676
3677 // Workaround: If routing to an non existing usb device, fail gracefully
3678 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003679 int card;
3680 if (audio_is_usb_in_device(val) &&
3681 (card = get_alive_usb_card(parms)) >= 0) {
3682
3683 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003684 status = -ENOSYS;
3685 } else {
3686
3687 in->device = val;
3688 /* If recording is in progress, change the tx device to new device */
3689 if (!in->standby) {
3690 ALOGV("update input routing change");
3691 // inform adm before actual routing to prevent glitches.
3692 if (adev->adm_on_routing_change) {
3693 adev->adm_on_routing_change(adev->adm_data,
3694 in->capture_handle);
3695 }
3696 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003697 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 }
3700 }
3701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003703 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704
3705 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003706 ALOGV("%s: exit: status(%d)", __func__, status);
3707 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708}
3709
Haynes Mathew George569b7482017-05-08 14:44:27 -07003710static char* in_get_parameters(const struct audio_stream *stream,
3711 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003712{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003713 struct stream_in *in = (struct stream_in *)stream;
3714 struct str_parms *query = str_parms_create_str(keys);
3715 char *str;
3716 struct str_parms *reply = str_parms_create();
3717 bool replied = false;
3718
3719 ALOGV("%s: enter: keys - %s", __func__, keys);
3720 replied |= stream_get_parameter_channels(query, reply,
3721 &in->supported_channel_masks[0]);
3722 replied |= stream_get_parameter_formats(query, reply,
3723 &in->supported_formats[0]);
3724 replied |= stream_get_parameter_rates(query, reply,
3725 &in->supported_sample_rates[0]);
3726 if (replied) {
3727 str = str_parms_to_str(reply);
3728 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003729 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003730 }
3731 str_parms_destroy(query);
3732 str_parms_destroy(reply);
3733 ALOGV("%s: exit: returns - %s", __func__, str);
3734 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735}
3736
Eric Laurent51f3c662018-04-10 18:21:34 -07003737static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738{
Eric Laurent51f3c662018-04-10 18:21:34 -07003739 struct stream_in *in = (struct stream_in *)stream;
3740 char mixer_ctl_name[128];
3741 struct mixer_ctl *ctl;
3742 int ctl_value;
3743
3744 ALOGV("%s: gain %f", __func__, gain);
3745
3746 if (stream == NULL)
3747 return -EINVAL;
3748
3749 /* in_set_gain() only used to silence MMAP capture for now */
3750 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3751 return -ENOSYS;
3752
3753 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3754
3755 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3756 if (!ctl) {
3757 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3758 __func__, mixer_ctl_name);
3759 return -ENOSYS;
3760 }
3761
3762 if (gain < RECORD_GAIN_MIN)
3763 gain = RECORD_GAIN_MIN;
3764 else if (gain > RECORD_GAIN_MAX)
3765 gain = RECORD_GAIN_MAX;
3766 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3767
3768 mixer_ctl_set_value(ctl, 0, ctl_value);
3769 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770}
3771
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003772static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3773{
3774 if (!stream || !parms)
3775 return;
3776
3777 struct stream_in *in = (struct stream_in *)stream;
3778 struct audio_device *adev = in->dev;
3779
3780 card_status_t status;
3781 int card;
3782 if (parse_snd_card_status(parms, &card, &status) < 0)
3783 return;
3784
3785 pthread_mutex_lock(&adev->lock);
3786 bool valid_cb = (card == adev->snd_card);
3787 pthread_mutex_unlock(&adev->lock);
3788
3789 if (!valid_cb)
3790 return;
3791
3792 lock_input_stream(in);
3793 if (in->card_status != status)
3794 in->card_status = status;
3795 pthread_mutex_unlock(&in->lock);
3796
3797 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3798 use_case_table[in->usecase],
3799 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3800
3801 // a better solution would be to report error back to AF and let
3802 // it put the stream to standby
3803 if (status == CARD_STATUS_OFFLINE)
3804 in_standby(&in->stream.common);
3805
3806 return;
3807}
3808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3810 size_t bytes)
3811{
3812 struct stream_in *in = (struct stream_in *)stream;
3813 struct audio_device *adev = in->dev;
3814 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003815 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003816 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003817
Eric Laurenta1478072015-09-21 17:21:52 -07003818 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003819 const size_t frame_size = audio_stream_in_frame_size(stream);
3820 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003821
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003822 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003823 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003824 /* Read from sound trigger HAL */
3825 audio_extn_sound_trigger_read(in, buffer, bytes);
3826 pthread_mutex_unlock(&in->lock);
3827 return bytes;
3828 }
3829
Eric Laurent0e46adf2016-12-16 12:49:24 -08003830 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3831 ret = -ENOSYS;
3832 goto exit;
3833 }
3834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003836 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003838 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 goto exit;
3841 }
3842 in->standby = 0;
3843 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844
Andy Hungd13f0d32017-06-12 13:58:37 -07003845 // errors that occur here are read errors.
3846 error_code = ERROR_CODE_READ;
3847
Haynes Mathew George03c40102016-01-29 17:57:48 -08003848 //what's the duration requested by the client?
3849 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3850 in->config.rate;
3851 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003852
Haynes Mathew George03c40102016-01-29 17:57:48 -08003853 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003855 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003856 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003857 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003858 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003859 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003860 if (ret < 0) {
3861 ALOGE("Failed to read w/err %s", strerror(errno));
3862 ret = -errno;
3863 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003864 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3865 if (bytes % 4 == 0) {
3866 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3867 int_buf_stream = buffer;
3868 for (size_t itt=0; itt < bytes/4 ; itt++) {
3869 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003870 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003871 } else {
3872 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3873 ret = -EINVAL;
3874 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003875 }
3876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 }
3878
Haynes Mathew George03c40102016-01-29 17:57:48 -08003879 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 /*
3882 * Instead of writing zeroes here, we could trust the hardware
3883 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003884 * 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 -08003885 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003886 if (ret == 0 && adev->mic_muted &&
3887 !voice_is_in_call_rec_stream(in) &&
3888 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003890 in->frames_muted += frames;
3891 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003892
3893exit:
3894 pthread_mutex_unlock(&in->lock);
3895
3896 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003897 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 in_standby(&in->stream.common);
3899 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003900 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003901 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003902 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003903 }
3904 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003905 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 }
3907 return bytes;
3908}
3909
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003910static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911{
3912 return 0;
3913}
3914
Andy Hung6ebe5962016-01-15 17:46:57 -08003915static int in_get_capture_position(const struct audio_stream_in *stream,
3916 int64_t *frames, int64_t *time)
3917{
3918 if (stream == NULL || frames == NULL || time == NULL) {
3919 return -EINVAL;
3920 }
3921 struct stream_in *in = (struct stream_in *)stream;
3922 int ret = -ENOSYS;
3923
3924 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003925 // note: ST sessions do not close the alsa pcm driver synchronously
3926 // on standby. Therefore, we may return an error even though the
3927 // pcm stream is still opened.
3928 if (in->standby) {
3929 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3930 "%s stream in standby but pcm not NULL for non ST session", __func__);
3931 goto exit;
3932 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003933 if (in->pcm) {
3934 struct timespec timestamp;
3935 unsigned int avail;
3936 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3937 *frames = in->frames_read + avail;
3938 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3939 ret = 0;
3940 }
3941 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003942exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003943 pthread_mutex_unlock(&in->lock);
3944 return ret;
3945}
3946
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003947static int add_remove_audio_effect(const struct audio_stream *stream,
3948 effect_handle_t effect,
3949 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003951 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003952 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003953 int status = 0;
3954 effect_descriptor_t desc;
3955
3956 status = (*effect)->get_descriptor(effect, &desc);
3957 if (status != 0)
3958 return status;
3959
Eric Laurenta1478072015-09-21 17:21:52 -07003960 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003961 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003962 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003963 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003964 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003965 in->enable_aec != enable &&
3966 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3967 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003968 if (!enable)
3969 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003970 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3971 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3972 adev->enable_voicerx = enable;
3973 struct audio_usecase *usecase;
3974 struct listnode *node;
3975 list_for_each(node, &adev->usecase_list) {
3976 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003977 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003978 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003979 }
3980 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003981 if (!in->standby)
3982 select_devices(in->dev, in->usecase);
3983 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003984 if (in->enable_ns != enable &&
3985 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3986 in->enable_ns = enable;
3987 if (!in->standby)
3988 select_devices(in->dev, in->usecase);
3989 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003990 pthread_mutex_unlock(&in->dev->lock);
3991 pthread_mutex_unlock(&in->lock);
3992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993 return 0;
3994}
3995
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003996static int in_add_audio_effect(const struct audio_stream *stream,
3997 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998{
Eric Laurent994a6932013-07-17 11:51:42 -07003999 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004000 return add_remove_audio_effect(stream, effect, true);
4001}
4002
4003static int in_remove_audio_effect(const struct audio_stream *stream,
4004 effect_handle_t effect)
4005{
Eric Laurent994a6932013-07-17 11:51:42 -07004006 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004007 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008}
4009
Eric Laurent0e46adf2016-12-16 12:49:24 -08004010static int in_stop(const struct audio_stream_in* stream)
4011{
4012 struct stream_in *in = (struct stream_in *)stream;
4013 struct audio_device *adev = in->dev;
4014
4015 int ret = -ENOSYS;
4016 ALOGV("%s", __func__);
4017 pthread_mutex_lock(&adev->lock);
4018 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4019 in->capture_started && in->pcm != NULL) {
4020 pcm_stop(in->pcm);
4021 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004022 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004023 }
4024 pthread_mutex_unlock(&adev->lock);
4025 return ret;
4026}
4027
4028static int in_start(const struct audio_stream_in* stream)
4029{
4030 struct stream_in *in = (struct stream_in *)stream;
4031 struct audio_device *adev = in->dev;
4032 int ret = -ENOSYS;
4033
4034 ALOGV("%s in %p", __func__, in);
4035 pthread_mutex_lock(&adev->lock);
4036 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4037 !in->capture_started && in->pcm != NULL) {
4038 if (!in->capture_started) {
4039 ret = start_input_stream(in);
4040 if (ret == 0) {
4041 in->capture_started = true;
4042 }
4043 }
4044 }
4045 pthread_mutex_unlock(&adev->lock);
4046 return ret;
4047}
4048
4049static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4050 int32_t min_size_frames,
4051 struct audio_mmap_buffer_info *info)
4052{
4053 struct stream_in *in = (struct stream_in *)stream;
4054 struct audio_device *adev = in->dev;
4055 int ret = 0;
4056 unsigned int offset1;
4057 unsigned int frames1;
4058 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004059 uint32_t mmap_size;
4060 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004061
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004062 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004063 pthread_mutex_lock(&adev->lock);
4064 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004065
Eric Laurent0e46adf2016-12-16 12:49:24 -08004066 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004067 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004068 ret = -EINVAL;
4069 goto exit;
4070 }
4071 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004072 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004073 ALOGV("%s in %p", __func__, in);
4074 ret = -ENOSYS;
4075 goto exit;
4076 }
4077 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4078 if (in->pcm_device_id < 0) {
4079 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4080 __func__, in->pcm_device_id, in->usecase);
4081 ret = -EINVAL;
4082 goto exit;
4083 }
Phil Burkbc991042017-02-24 08:06:44 -08004084
4085 adjust_mmap_period_count(&in->config, min_size_frames);
4086
Eric Laurent0e46adf2016-12-16 12:49:24 -08004087 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4088 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4089 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4090 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4091 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4092 step = "open";
4093 ret = -ENODEV;
4094 goto exit;
4095 }
4096
4097 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4098 if (ret < 0) {
4099 step = "begin";
4100 goto exit;
4101 }
4102 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004103 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004104 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004105 ret = platform_get_mmap_data_fd(adev->platform,
4106 in->pcm_device_id, 1 /*capture*/,
4107 &info->shared_memory_fd,
4108 &mmap_size);
4109 if (ret < 0) {
4110 // Fall back to non exclusive mode
4111 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4112 } else {
4113 if (mmap_size < buffer_size) {
4114 step = "mmap";
4115 goto exit;
4116 }
4117 // FIXME: indicate exclusive mode support by returning a negative buffer size
4118 info->buffer_size_frames *= -1;
4119 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004120
Haynes Mathew George96483a22017-03-28 14:52:47 -07004121 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004122
4123 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4124 if (ret < 0) {
4125 step = "commit";
4126 goto exit;
4127 }
4128
Phil Burkbc991042017-02-24 08:06:44 -08004129 in->standby = false;
4130 ret = 0;
4131
Eric Laurent0e46adf2016-12-16 12:49:24 -08004132 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4133 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004134
4135exit:
4136 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004137 if (in->pcm == NULL) {
4138 ALOGE("%s: %s - %d", __func__, step, ret);
4139 } else {
4140 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004141 pcm_close(in->pcm);
4142 in->pcm = NULL;
4143 }
4144 }
4145 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004146 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004147 return ret;
4148}
4149
4150static int in_get_mmap_position(const struct audio_stream_in *stream,
4151 struct audio_mmap_position *position)
4152{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004153 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004154 struct stream_in *in = (struct stream_in *)stream;
4155 ALOGVV("%s", __func__);
4156 if (position == NULL) {
4157 return -EINVAL;
4158 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004159 lock_input_stream(in);
4160 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4161 in->pcm == NULL) {
4162 ret = -ENOSYS;
4163 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004164 }
4165 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004166 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004167 if (ret < 0) {
4168 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004169 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004170 }
Andy Hungfc044e12017-03-20 09:24:22 -07004171 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004172exit:
4173 pthread_mutex_unlock(&in->lock);
4174 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004175}
4176
jiabin8962a4d2018-03-19 18:21:24 -07004177static int in_get_active_microphones(const struct audio_stream_in *stream,
4178 struct audio_microphone_characteristic_t *mic_array,
4179 size_t *mic_count) {
4180 struct stream_in *in = (struct stream_in *)stream;
4181 struct audio_device *adev = in->dev;
4182 ALOGVV("%s", __func__);
4183
4184 lock_input_stream(in);
4185 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004186 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004187 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004188 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004189 pthread_mutex_unlock(&adev->lock);
4190 pthread_mutex_unlock(&in->lock);
4191
4192 return ret;
4193}
4194
4195static int adev_get_microphones(const struct audio_hw_device *dev,
4196 struct audio_microphone_characteristic_t *mic_array,
4197 size_t *mic_count) {
4198 struct audio_device *adev = (struct audio_device *)dev;
4199 ALOGVV("%s", __func__);
4200
4201 pthread_mutex_lock(&adev->lock);
4202 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4203 pthread_mutex_unlock(&adev->lock);
4204
4205 return ret;
4206}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004208static int adev_open_output_stream(struct audio_hw_device *dev,
4209 audio_io_handle_t handle,
4210 audio_devices_t devices,
4211 audio_output_flags_t flags,
4212 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004213 struct audio_stream_out **stream_out,
4214 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215{
4216 struct audio_device *adev = (struct audio_device *)dev;
4217 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004218 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004219 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4220 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4221 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222
Andy Hungd9653bd2017-08-01 19:31:39 -07004223 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4224 return -ENOSYS;
4225 }
4226
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004227 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4228 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 *stream_out = NULL;
4230 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4231
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004232 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234 if (devices == AUDIO_DEVICE_NONE)
4235 devices = AUDIO_DEVICE_OUT_SPEAKER;
4236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 out->flags = flags;
4238 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004239 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004240 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004241 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242
4243 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004244 if ((is_hdmi || is_usb_dev) &&
4245 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4246 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4247 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004248 audio_format_t req_format = config->format;
4249 audio_channel_mask_t req_channel_mask = config->channel_mask;
4250 uint32_t req_sample_rate = config->sample_rate;
4251
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004252 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004253 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004254 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004255 if (config->sample_rate == 0)
4256 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004257 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004258 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4259 if (config->format == AUDIO_FORMAT_DEFAULT)
4260 config->format = AUDIO_FORMAT_PCM_16_BIT;
4261 } else if (is_usb_dev) {
4262 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4263 &config->format,
4264 &out->supported_formats[0],
4265 MAX_SUPPORTED_FORMATS,
4266 &config->channel_mask,
4267 &out->supported_channel_masks[0],
4268 MAX_SUPPORTED_CHANNEL_MASKS,
4269 &config->sample_rate,
4270 &out->supported_sample_rates[0],
4271 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004272 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004273 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004274 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004275 if (ret != 0) {
4276 // For MMAP NO IRQ, allow conversions in ADSP
4277 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4278 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004279
Eric Laurentab805ee2018-03-30 12:20:38 -07004280 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4281 config->sample_rate = req_sample_rate;
4282 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4283 config->channel_mask = req_channel_mask;
4284 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4285 config->format = req_format;
4286 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004287
Haynes Mathew George569b7482017-05-08 14:44:27 -07004288 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004289 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004290 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004291 if (is_hdmi) {
4292 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4293 out->config = pcm_config_hdmi_multi;
4294 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4295 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4296 out->config = pcm_config_mmap_playback;
4297 out->stream.start = out_start;
4298 out->stream.stop = out_stop;
4299 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4300 out->stream.get_mmap_position = out_get_mmap_position;
4301 } else {
4302 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4303 out->config = pcm_config_hifi;
4304 }
4305
4306 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004307 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004308 if (is_hdmi) {
4309 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4310 audio_bytes_per_sample(out->format));
4311 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004312 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004313 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004314 pthread_mutex_lock(&adev->lock);
4315 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4316 pthread_mutex_unlock(&adev->lock);
4317
4318 // reject offload during card offline to allow
4319 // fallback to s/w paths
4320 if (offline) {
4321 ret = -ENODEV;
4322 goto error_open;
4323 }
4324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4326 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4327 ALOGE("%s: Unsupported Offload information", __func__);
4328 ret = -EINVAL;
4329 goto error_open;
4330 }
4331 if (!is_supported_format(config->offload_info.format)) {
4332 ALOGE("%s: Unsupported audio format", __func__);
4333 ret = -EINVAL;
4334 goto error_open;
4335 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004336 out->sample_rate = config->offload_info.sample_rate;
4337 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4338 out->channel_mask = config->offload_info.channel_mask;
4339 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4340 out->channel_mask = config->channel_mask;
4341 else
4342 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4343
4344 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004345
4346 out->compr_config.codec = (struct snd_codec *)
4347 calloc(1, sizeof(struct snd_codec));
4348
4349 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004350
4351 out->stream.set_callback = out_set_callback;
4352 out->stream.pause = out_pause;
4353 out->stream.resume = out_resume;
4354 out->stream.drain = out_drain;
4355 out->stream.flush = out_flush;
4356
4357 out->compr_config.codec->id =
4358 get_snd_codec_id(config->offload_info.format);
4359 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4360 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004361 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004362 out->compr_config.codec->bit_rate =
4363 config->offload_info.bit_rate;
4364 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004365 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004366 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4367
4368 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4369 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004370
4371 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004372 create_offload_callback_thread(out);
4373 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4374 __func__, config->offload_info.version,
4375 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004376 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4377 switch (config->sample_rate) {
4378 case 0:
4379 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4380 break;
4381 case 8000:
4382 case 16000:
4383 case 48000:
4384 out->sample_rate = config->sample_rate;
4385 break;
4386 default:
4387 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4388 config->sample_rate);
4389 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4390 ret = -EINVAL;
4391 goto error_open;
4392 }
4393 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4394 switch (config->channel_mask) {
4395 case AUDIO_CHANNEL_NONE:
4396 case AUDIO_CHANNEL_OUT_STEREO:
4397 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4398 break;
4399 default:
4400 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4401 config->channel_mask);
4402 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4403 ret = -EINVAL;
4404 goto error_open;
4405 }
4406 switch (config->format) {
4407 case AUDIO_FORMAT_DEFAULT:
4408 case AUDIO_FORMAT_PCM_16_BIT:
4409 out->format = AUDIO_FORMAT_PCM_16_BIT;
4410 break;
4411 default:
4412 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4413 config->format);
4414 config->format = AUDIO_FORMAT_PCM_16_BIT;
4415 ret = -EINVAL;
4416 goto error_open;
4417 }
4418
4419 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004420 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004421 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004422 case 0:
4423 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4424 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004425 case 8000:
4426 case 16000:
4427 case 48000:
4428 out->sample_rate = config->sample_rate;
4429 break;
4430 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004431 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4432 config->sample_rate);
4433 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4434 ret = -EINVAL;
4435 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004436 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004437 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4438 switch (config->channel_mask) {
4439 case AUDIO_CHANNEL_NONE:
4440 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4441 break;
4442 case AUDIO_CHANNEL_OUT_STEREO:
4443 out->channel_mask = config->channel_mask;
4444 break;
4445 default:
4446 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4447 config->channel_mask);
4448 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4449 ret = -EINVAL;
4450 break;
4451 }
4452 switch (config->format) {
4453 case AUDIO_FORMAT_DEFAULT:
4454 out->format = AUDIO_FORMAT_PCM_16_BIT;
4455 break;
4456 case AUDIO_FORMAT_PCM_16_BIT:
4457 out->format = config->format;
4458 break;
4459 default:
4460 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4461 config->format);
4462 config->format = AUDIO_FORMAT_PCM_16_BIT;
4463 ret = -EINVAL;
4464 break;
4465 }
4466 if (ret != 0)
4467 goto error_open;
4468
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004469 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4470 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004471 out->config.rate = out->sample_rate;
4472 out->config.channels =
4473 audio_channel_count_from_out_mask(out->channel_mask);
4474 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004475 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004476 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4477 switch (config->sample_rate) {
4478 case 0:
4479 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4480 break;
4481 case 8000:
4482 case 16000:
4483 case 32000:
4484 case 48000:
4485 out->sample_rate = config->sample_rate;
4486 break;
4487 default:
4488 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4489 config->sample_rate);
4490 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4491 ret = -EINVAL;
4492 break;
4493 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004494 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495 switch (config->channel_mask) {
4496 case AUDIO_CHANNEL_NONE:
4497 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4498 break;
4499 case AUDIO_CHANNEL_OUT_STEREO:
4500 out->channel_mask = config->channel_mask;
4501 break;
4502 default:
4503 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4504 config->channel_mask);
4505 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4506 ret = -EINVAL;
4507 break;
4508 }
4509 switch (config->format) {
4510 case AUDIO_FORMAT_DEFAULT:
4511 out->format = AUDIO_FORMAT_PCM_16_BIT;
4512 break;
4513 case AUDIO_FORMAT_PCM_16_BIT:
4514 out->format = config->format;
4515 break;
4516 default:
4517 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4518 config->format);
4519 config->format = AUDIO_FORMAT_PCM_16_BIT;
4520 ret = -EINVAL;
4521 break;
4522 }
4523 if (ret != 0)
4524 goto error_open;
4525
vivek mehtaa68fea62017-06-08 19:04:02 -07004526 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004527 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4528 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004529 out->config.rate = out->sample_rate;
4530 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004531 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004532 out->sample_rate,
4533 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004534 out->config.channels,
4535 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004536 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004537 out->config.period_size = buffer_size / frame_size;
4538 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4539 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004540 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004541 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004542 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4543 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004544 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004545 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4546 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004547 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004548 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004549 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004550 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004551 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004552 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4553 out->config = pcm_config_mmap_playback;
4554 out->stream.start = out_start;
4555 out->stream.stop = out_stop;
4556 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4557 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004558 } else {
4559 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4560 out->config = pcm_config_low_latency;
4561 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004562
4563 if (config->sample_rate == 0) {
4564 out->sample_rate = out->config.rate;
4565 } else {
4566 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004567 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004568 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4569 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4570 } else {
4571 out->channel_mask = config->channel_mask;
4572 }
4573 if (config->format == AUDIO_FORMAT_DEFAULT)
4574 out->format = audio_format_from_pcm_format(out->config.format);
4575 else if (!audio_is_linear_pcm(config->format)) {
4576 config->format = AUDIO_FORMAT_PCM_16_BIT;
4577 ret = -EINVAL;
4578 goto error_open;
4579 } else {
4580 out->format = config->format;
4581 }
4582
4583 out->config.rate = out->sample_rate;
4584 out->config.channels =
4585 audio_channel_count_from_out_mask(out->channel_mask);
4586 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4587 out->config.format = pcm_format_from_audio_format(out->format);
4588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004590
4591 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4592 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004593 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004594 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4595 __func__, config->sample_rate, config->format, config->channel_mask);
4596 config->sample_rate = out->sample_rate;
4597 config->format = out->format;
4598 config->channel_mask = out->channel_mask;
4599 ret = -EINVAL;
4600 goto error_open;
4601 }
4602
Andy Hung6fcba9c2014-03-18 11:53:32 -07004603 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4604 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004606 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004607 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004608 adev->primary_output = out;
4609 else {
4610 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004611 ret = -EEXIST;
4612 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004613 }
4614 }
4615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 /* Check if this usecase is already existing */
4617 pthread_mutex_lock(&adev->lock);
4618 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4619 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004621 ret = -EEXIST;
4622 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004623 }
4624 pthread_mutex_unlock(&adev->lock);
4625
4626 out->stream.common.get_sample_rate = out_get_sample_rate;
4627 out->stream.common.set_sample_rate = out_set_sample_rate;
4628 out->stream.common.get_buffer_size = out_get_buffer_size;
4629 out->stream.common.get_channels = out_get_channels;
4630 out->stream.common.get_format = out_get_format;
4631 out->stream.common.set_format = out_set_format;
4632 out->stream.common.standby = out_standby;
4633 out->stream.common.dump = out_dump;
4634 out->stream.common.set_parameters = out_set_parameters;
4635 out->stream.common.get_parameters = out_get_parameters;
4636 out->stream.common.add_audio_effect = out_add_audio_effect;
4637 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4638 out->stream.get_latency = out_get_latency;
4639 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004640#ifdef NO_AUDIO_OUT
4641 out->stream.write = out_write_for_no_output;
4642#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004644#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 out->stream.get_render_position = out_get_render_position;
4646 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004647 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648
Eric Laurent0e46adf2016-12-16 12:49:24 -08004649 if (out->realtime)
4650 out->af_period_multiplier = af_period_multiplier;
4651 else
4652 out->af_period_multiplier = 1;
4653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004655 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004656 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004658 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004659 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004660 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 config->format = out->stream.common.get_format(&out->stream.common);
4663 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4664 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4665
Kevin Rocarda325aa22018-04-03 09:15:52 -07004666 register_format(out->format, out->supported_formats);
4667 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4668 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4669
Andy Hunga452b0a2017-03-15 14:51:15 -07004670 out->error_log = error_log_create(
4671 ERROR_LOG_ENTRIES,
4672 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4673
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004674 /*
4675 By locking output stream before registering, we allow the callback
4676 to update stream's state only after stream's initial state is set to
4677 adev state.
4678 */
4679 lock_output_stream(out);
4680 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4681 pthread_mutex_lock(&adev->lock);
4682 out->card_status = adev->card_status;
4683 pthread_mutex_unlock(&adev->lock);
4684 pthread_mutex_unlock(&out->lock);
4685
vivek mehta4a824772017-06-08 19:05:49 -07004686 stream_app_type_cfg_init(&out->app_type_cfg);
4687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004689
Eric Laurent994a6932013-07-17 11:51:42 -07004690 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004692
4693error_open:
4694 free(out);
4695 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004696 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004697 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004698}
4699
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004700static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 struct audio_stream_out *stream)
4702{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004703 struct stream_out *out = (struct stream_out *)stream;
4704 struct audio_device *adev = out->dev;
4705
Eric Laurent994a6932013-07-17 11:51:42 -07004706 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004707
4708 // must deregister from sndmonitor first to prevent races
4709 // between the callback and close_stream
4710 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004712 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4713 destroy_offload_callback_thread(out);
4714
4715 if (out->compr_config.codec != NULL)
4716 free(out->compr_config.codec);
4717 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004718
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004719 out->a2dp_compress_mute = false;
4720
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004721 if (adev->voice_tx_output == out)
4722 adev->voice_tx_output = NULL;
4723
Andy Hunga452b0a2017-03-15 14:51:15 -07004724 error_log_destroy(out->error_log);
4725 out->error_log = NULL;
4726
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004727 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004728 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004729 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004730 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004731 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004732}
4733
4734static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4735{
4736 struct audio_device *adev = (struct audio_device *)dev;
4737 struct str_parms *parms;
4738 char *str;
4739 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004740 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004742 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004743 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744
Joe Onorato188b6222016-03-01 11:02:27 -08004745 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004746
4747 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748
4749 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004750 status = voice_set_parameters(adev, parms);
4751 if (status != 0) {
4752 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004753 }
4754
4755 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4756 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004757 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4759 adev->bluetooth_nrec = true;
4760 else
4761 adev->bluetooth_nrec = false;
4762 }
4763
4764 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4765 if (ret >= 0) {
4766 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4767 adev->screen_off = false;
4768 else
4769 adev->screen_off = true;
4770 }
4771
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004772 ret = str_parms_get_int(parms, "rotation", &val);
4773 if (ret >= 0) {
4774 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004775 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004776 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004777 // FIXME: note that the code below assumes that the speakers are in the correct placement
4778 // relative to the user when the device is rotated 90deg from its default rotation. This
4779 // assumption is device-specific, not platform-specific like this code.
4780 case 270:
4781 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07004782 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004783 break;
4784 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004785 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07004786 camera_rotation = CAMERA_ROTATION_PORTRAIT;
4787 break;
4788 case 90:
4789 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004790 break;
4791 default:
4792 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004793 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004794 }
Eric Laurent03f09432014-03-25 18:09:11 -07004795 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004796 // check and set swap
4797 // - check if orientation changed and speaker active
4798 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07004799 adev->camera_orientation =
4800 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
4801#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07004802 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07004803#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004804 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004805 }
4806
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004807 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4808 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004809 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004810 }
4811
David Linee3fe402017-03-13 10:00:42 -07004812 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4813 if (ret >= 0) {
4814 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004815 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004816 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4817 if (ret >= 0) {
4818 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004819 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004820 }
Eric Laurent99dab492017-06-17 15:19:08 -07004821 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004822 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4823 if (ret >= 0) {
4824 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004825 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004826 }
4827 }
4828 }
4829
4830 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4831 if (ret >= 0) {
4832 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004833 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004834 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4835 if (ret >= 0) {
4836 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004837 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004838 }
Eric Laurent99dab492017-06-17 15:19:08 -07004839 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004840 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4841 if (ret >= 0) {
4842 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004843 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004844 }
4845 }
4846 }
4847
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004848 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004849 audio_extn_ma_set_parameters(adev, parms);
4850
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004851 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4852 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004853 struct audio_usecase *usecase;
4854 struct listnode *node;
4855 list_for_each(node, &adev->usecase_list) {
4856 usecase = node_to_item(node, struct audio_usecase, list);
4857 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004858 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004859 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4860
4861 pthread_mutex_unlock(&adev->lock);
4862 lock_output_stream(usecase->stream.out);
4863 pthread_mutex_lock(&adev->lock);
4864 audio_extn_a2dp_set_handoff_mode(true);
4865 // force device switch to reconfigure encoder
4866 select_devices(adev, usecase->id);
4867 audio_extn_a2dp_set_handoff_mode(false);
4868 pthread_mutex_unlock(&usecase->stream.out->lock);
4869 break;
4870 }
4871 }
4872 }
4873
Eric Laurent5f4ca952018-10-19 17:33:43 -07004874 //FIXME: to be replaced by proper video capture properties API
4875 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
4876 if (ret >= 0) {
4877 int camera_facing = CAMERA_FACING_BACK;
4878 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
4879 camera_facing = CAMERA_FACING_FRONT;
4880 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
4881 camera_facing = CAMERA_FACING_BACK;
4882 else {
4883 ALOGW("%s: invalid camera facing value: %s", __func__, value);
4884 goto done;
4885 }
4886 adev->camera_orientation =
4887 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
4888 struct audio_usecase *usecase;
4889 struct listnode *node;
4890 list_for_each(node, &adev->usecase_list) {
4891 usecase = node_to_item(node, struct audio_usecase, list);
4892 struct stream_in *in = usecase->stream.in;
4893 if (usecase->type == PCM_CAPTURE && in != NULL &&
4894 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
4895 select_devices(adev, in->usecase);
4896 }
4897 }
4898 }
4899
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004900done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004902 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004903 ALOGV("%s: exit with code(%d)", __func__, status);
4904 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004905}
4906
4907static char* adev_get_parameters(const struct audio_hw_device *dev,
4908 const char *keys)
4909{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004910 struct audio_device *adev = (struct audio_device *)dev;
4911 struct str_parms *reply = str_parms_create();
4912 struct str_parms *query = str_parms_create_str(keys);
4913 char *str;
4914
4915 pthread_mutex_lock(&adev->lock);
4916
4917 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004918 audio_extn_a2dp_get_parameters(query, reply);
4919
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004920 str = str_parms_to_str(reply);
4921 str_parms_destroy(query);
4922 str_parms_destroy(reply);
4923
4924 pthread_mutex_unlock(&adev->lock);
4925 ALOGV("%s: exit: returns - %s", __func__, str);
4926 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927}
4928
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004929static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930{
4931 return 0;
4932}
4933
Haynes Mathew George5191a852013-09-11 14:19:36 -07004934static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4935{
4936 int ret;
4937 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004938
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004939 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4940
Haynes Mathew George5191a852013-09-11 14:19:36 -07004941 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004942 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004943 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004944
Haynes Mathew George5191a852013-09-11 14:19:36 -07004945 return ret;
4946}
4947
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004948static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004949{
4950 return -ENOSYS;
4951}
4952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004953static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4954 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955{
4956 return -ENOSYS;
4957}
4958
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004959static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960{
4961 return -ENOSYS;
4962}
4963
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004964static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004965{
4966 return -ENOSYS;
4967}
4968
4969static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4970{
4971 struct audio_device *adev = (struct audio_device *)dev;
4972
4973 pthread_mutex_lock(&adev->lock);
4974 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004975 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004977 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4978 voice_is_in_call(adev)) {
4979 voice_stop_call(adev);
4980 adev->current_call_output = NULL;
4981 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 }
4983 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004984
4985 audio_extn_extspk_set_mode(adev->extspk, mode);
4986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987 return 0;
4988}
4989
4990static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4991{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004992 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004993 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994
Eric Laurent2bafff12016-03-17 12:17:23 -07004995 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004996 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004997 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4998 ret = audio_extn_hfp_set_mic_mute(adev, state);
4999 } else {
5000 ret = voice_set_mic_mute(adev, state);
5001 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005002 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005003 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005004
5005 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006}
5007
5008static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5009{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005010 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005011 return 0;
5012}
5013
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005014static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015 const struct audio_config *config)
5016{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005017 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005018
Eric Laurent74b55762017-07-09 17:04:53 -07005019 /* Don't know if USB HIFI in this context so use true to be conservative */
5020 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5021 true /*is_usb_hifi */) != 0)
5022 return 0;
5023
vivek mehtaa68fea62017-06-08 19:04:02 -07005024 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5025 config->sample_rate, config->format,
5026 channel_count,
5027 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005028}
5029
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005030static bool adev_input_allow_hifi_record(struct audio_device *adev,
5031 audio_devices_t devices,
5032 audio_input_flags_t flags,
5033 audio_source_t source) {
5034 const bool allowed = true;
5035
5036 if (!audio_is_usb_in_device(devices))
5037 return !allowed;
5038
5039 switch (flags) {
5040 case AUDIO_INPUT_FLAG_NONE:
5041 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5042 break;
5043 default:
5044 return !allowed;
5045 }
5046
5047 switch (source) {
5048 case AUDIO_SOURCE_DEFAULT:
5049 case AUDIO_SOURCE_MIC:
5050 case AUDIO_SOURCE_UNPROCESSED:
5051 break;
5052 default:
5053 return !allowed;
5054 }
5055
5056 switch (adev->mode) {
5057 case 0:
5058 break;
5059 default:
5060 return !allowed;
5061 }
5062
5063 return allowed;
5064}
5065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005066static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005067 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068 audio_devices_t devices,
5069 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005070 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005071 audio_input_flags_t flags,
5072 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005073 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005074{
5075 struct audio_device *adev = (struct audio_device *)dev;
5076 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005077 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005078 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005079 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005080 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005081 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5082 devices,
5083 flags,
5084 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005085 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5086 " sample_rate %u, channel_mask %#x, format %#x",
5087 __func__, flags, is_usb_dev, may_use_hifi_record,
5088 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005089 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005090
Andy Hungd9653bd2017-08-01 19:31:39 -07005091 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5092 return -ENOSYS;
5093 }
5094
Eric Laurent74b55762017-07-09 17:04:53 -07005095 if (!(is_usb_dev && may_use_hifi_record)) {
5096 if (config->sample_rate == 0)
5097 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5098 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5099 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5100 if (config->format == AUDIO_FORMAT_DEFAULT)
5101 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005102
Eric Laurent74b55762017-07-09 17:04:53 -07005103 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5104
5105 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5106 return -EINVAL;
5107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005109 if (audio_extn_tfa_98xx_is_supported() &&
5110 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005111 return -EINVAL;
5112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5114
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005115 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005116 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118 in->stream.common.get_sample_rate = in_get_sample_rate;
5119 in->stream.common.set_sample_rate = in_set_sample_rate;
5120 in->stream.common.get_buffer_size = in_get_buffer_size;
5121 in->stream.common.get_channels = in_get_channels;
5122 in->stream.common.get_format = in_get_format;
5123 in->stream.common.set_format = in_set_format;
5124 in->stream.common.standby = in_standby;
5125 in->stream.common.dump = in_dump;
5126 in->stream.common.set_parameters = in_set_parameters;
5127 in->stream.common.get_parameters = in_get_parameters;
5128 in->stream.common.add_audio_effect = in_add_audio_effect;
5129 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5130 in->stream.set_gain = in_set_gain;
5131 in->stream.read = in_read;
5132 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005133 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005134 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135
5136 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005137 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005138 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005139 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005140 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005141 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005142
Andy Hung88ce1d92018-10-29 18:31:12 -07005143 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005144 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5145 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5146 /* Force channel config requested to mono if incall
5147 record is being requested for only uplink/downlink */
5148 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5149 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5150 ret = -EINVAL;
5151 goto err_open;
5152 }
5153 }
5154
Haynes Mathew George569b7482017-05-08 14:44:27 -07005155 if (is_usb_dev && may_use_hifi_record) {
5156 /* HiFi record selects an appropriate format, channel, rate combo
5157 depending on sink capabilities*/
5158 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5159 &config->format,
5160 &in->supported_formats[0],
5161 MAX_SUPPORTED_FORMATS,
5162 &config->channel_mask,
5163 &in->supported_channel_masks[0],
5164 MAX_SUPPORTED_CHANNEL_MASKS,
5165 &config->sample_rate,
5166 &in->supported_sample_rates[0],
5167 MAX_SUPPORTED_SAMPLE_RATES);
5168 if (ret != 0) {
5169 ret = -EINVAL;
5170 goto err_open;
5171 }
Eric Laurent74b55762017-07-09 17:04:53 -07005172 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005173 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005174 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005175 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5176 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5177 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5178 bool ret_error = false;
5179 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5180 from HAL is 8_24
5181 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5182 8_24 return error indicating supported format is 8_24
5183 *> In case of any other source requesting 24 bit or float return error
5184 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005185
vivek mehta57ff9b52016-04-28 14:13:08 -07005186 on error flinger will retry with supported format passed
5187 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005188 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005189 config->format = AUDIO_FORMAT_PCM_16_BIT;
5190 ret_error = true;
5191 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5192 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5193 ret_error = true;
5194 }
5195
5196 if (ret_error) {
5197 ret = -EINVAL;
5198 goto err_open;
5199 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005200 }
5201
vivek mehta57ff9b52016-04-28 14:13:08 -07005202 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005203 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005206 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5207 if (config->sample_rate == 0)
5208 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5209 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5210 config->sample_rate != 8000) {
5211 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5212 ret = -EINVAL;
5213 goto err_open;
5214 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005215
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005216 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5217 config->format = AUDIO_FORMAT_PCM_16_BIT;
5218 ret = -EINVAL;
5219 goto err_open;
5220 }
5221
5222 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5223 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005224 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005225 } else if (is_usb_dev && may_use_hifi_record) {
5226 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5227 in->config = pcm_config_audio_capture;
5228 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005229 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5230 config->sample_rate,
5231 config->format,
5232 channel_count,
5233 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005234 in->config.period_size = buffer_size / frame_size;
5235 in->config.rate = config->sample_rate;
5236 in->af_period_multiplier = 1;
5237 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005238 } else {
5239 in->usecase = USECASE_AUDIO_RECORD;
5240 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005241 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005242 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005243#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005244 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005245#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005246 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005247 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005248 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005249 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005250 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5251 config->sample_rate,
5252 config->format,
5253 channel_count,
5254 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005255 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005256 in->config.rate = config->sample_rate;
5257 in->af_period_multiplier = 1;
5258 } else {
5259 // period size is left untouched for rt mode playback
5260 in->config = pcm_config_audio_capture_rt;
5261 in->af_period_multiplier = af_period_multiplier;
5262 }
5263 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5264 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005265 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005266 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5267 in->config = pcm_config_mmap_capture;
5268 in->stream.start = in_start;
5269 in->stream.stop = in_stop;
5270 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5271 in->stream.get_mmap_position = in_get_mmap_position;
5272 in->af_period_multiplier = 1;
5273 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005274 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005275 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005276 (config->sample_rate == 8000 ||
5277 config->sample_rate == 16000 ||
5278 config->sample_rate == 32000 ||
5279 config->sample_rate == 48000) &&
5280 channel_count == 1) {
5281 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5282 in->config = pcm_config_audio_capture;
5283 frame_size = audio_stream_in_frame_size(&in->stream);
5284 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5285 config->sample_rate,
5286 config->format,
5287 channel_count, false /*is_low_latency*/);
5288 in->config.period_size = buffer_size / frame_size;
5289 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5290 in->config.rate = config->sample_rate;
5291 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005292 } else {
5293 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005294 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005295 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5296 config->sample_rate,
5297 config->format,
5298 channel_count,
5299 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005300 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005301 in->config.rate = config->sample_rate;
5302 in->af_period_multiplier = 1;
5303 }
5304 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5305 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005306 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005308 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005309 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005310
Kevin Rocarda325aa22018-04-03 09:15:52 -07005311
5312 register_format(in->format, in->supported_formats);
5313 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5314 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5315
Andy Hungd13f0d32017-06-12 13:58:37 -07005316 in->error_log = error_log_create(
5317 ERROR_LOG_ENTRIES,
5318 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5319
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005320 /* This stream could be for sound trigger lab,
5321 get sound trigger pcm if present */
5322 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005324 lock_input_stream(in);
5325 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5326 pthread_mutex_lock(&adev->lock);
5327 in->card_status = adev->card_status;
5328 pthread_mutex_unlock(&adev->lock);
5329 pthread_mutex_unlock(&in->lock);
5330
vivek mehta4a824772017-06-08 19:05:49 -07005331 stream_app_type_cfg_init(&in->app_type_cfg);
5332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005333 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005334 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005335 return 0;
5336
5337err_open:
5338 free(in);
5339 *stream_in = NULL;
5340 return ret;
5341}
5342
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005343static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005344 struct audio_stream_in *stream)
5345{
Andy Hungd13f0d32017-06-12 13:58:37 -07005346 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005347 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005348
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005349 // must deregister from sndmonitor first to prevent races
5350 // between the callback and close_stream
5351 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005352 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005353
5354 error_log_destroy(in->error_log);
5355 in->error_log = NULL;
5356
Andy Hung0dbb52b2017-08-09 13:51:38 -07005357 pthread_mutex_destroy(&in->pre_lock);
5358 pthread_mutex_destroy(&in->lock);
5359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005360 free(stream);
5361
5362 return;
5363}
5364
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005365static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366{
5367 return 0;
5368}
5369
Andy Hung31aca912014-03-20 17:14:59 -07005370/* verifies input and output devices and their capabilities.
5371 *
5372 * This verification is required when enabling extended bit-depth or
5373 * sampling rates, as not all qcom products support it.
5374 *
5375 * Suitable for calling only on initialization such as adev_open().
5376 * It fills the audio_device use_case_table[] array.
5377 *
5378 * Has a side-effect that it needs to configure audio routing / devices
5379 * in order to power up the devices and read the device parameters.
5380 * It does not acquire any hw device lock. Should restore the devices
5381 * back to "normal state" upon completion.
5382 */
5383static int adev_verify_devices(struct audio_device *adev)
5384{
5385 /* enumeration is a bit difficult because one really wants to pull
5386 * the use_case, device id, etc from the hidden pcm_device_table[].
5387 * In this case there are the following use cases and device ids.
5388 *
5389 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5390 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005391 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005392 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5393 * [USECASE_AUDIO_RECORD] = {0, 0},
5394 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5395 * [USECASE_VOICE_CALL] = {2, 2},
5396 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005397 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005398 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5399 */
5400
5401 /* should be the usecases enabled in adev_open_input_stream() */
5402 static const int test_in_usecases[] = {
5403 USECASE_AUDIO_RECORD,
5404 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5405 };
5406 /* should be the usecases enabled in adev_open_output_stream()*/
5407 static const int test_out_usecases[] = {
5408 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5409 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5410 };
5411 static const usecase_type_t usecase_type_by_dir[] = {
5412 PCM_PLAYBACK,
5413 PCM_CAPTURE,
5414 };
5415 static const unsigned flags_by_dir[] = {
5416 PCM_OUT,
5417 PCM_IN,
5418 };
5419
5420 size_t i;
5421 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005422 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005423 char info[512]; /* for possible debug info */
5424
5425 for (dir = 0; dir < 2; ++dir) {
5426 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5427 const unsigned flags_dir = flags_by_dir[dir];
5428 const size_t testsize =
5429 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5430 const int *testcases =
5431 dir ? test_in_usecases : test_out_usecases;
5432 const audio_devices_t audio_device =
5433 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5434
5435 for (i = 0; i < testsize; ++i) {
5436 const audio_usecase_t audio_usecase = testcases[i];
5437 int device_id;
5438 snd_device_t snd_device;
5439 struct pcm_params **pparams;
5440 struct stream_out out;
5441 struct stream_in in;
5442 struct audio_usecase uc_info;
5443 int retval;
5444
5445 pparams = &adev->use_case_table[audio_usecase];
5446 pcm_params_free(*pparams); /* can accept null input */
5447 *pparams = NULL;
5448
5449 /* find the device ID for the use case (signed, for error) */
5450 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5451 if (device_id < 0)
5452 continue;
5453
5454 /* prepare structures for device probing */
5455 memset(&uc_info, 0, sizeof(uc_info));
5456 uc_info.id = audio_usecase;
5457 uc_info.type = usecase_type;
5458 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005459 memset(&in, 0, sizeof(in));
5460 in.device = audio_device;
5461 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5462 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005463 }
5464 memset(&out, 0, sizeof(out));
5465 out.devices = audio_device; /* only field needed in select_devices */
5466 uc_info.stream.out = &out;
5467 uc_info.devices = audio_device;
5468 uc_info.in_snd_device = SND_DEVICE_NONE;
5469 uc_info.out_snd_device = SND_DEVICE_NONE;
5470 list_add_tail(&adev->usecase_list, &uc_info.list);
5471
5472 /* select device - similar to start_(in/out)put_stream() */
5473 retval = select_devices(adev, audio_usecase);
5474 if (retval >= 0) {
5475 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5476#if LOG_NDEBUG == 0
5477 if (*pparams) {
5478 ALOGV("%s: (%s) card %d device %d", __func__,
5479 dir ? "input" : "output", card_id, device_id);
5480 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005481 } else {
5482 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5483 }
5484#endif
5485 }
5486
5487 /* deselect device - similar to stop_(in/out)put_stream() */
5488 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005489 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005490 /* 2. Disable the rx device */
5491 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005492 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005493 list_remove(&uc_info.list);
5494 }
5495 }
Andy Hung31aca912014-03-20 17:14:59 -07005496 return 0;
5497}
5498
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005499static int adev_close(hw_device_t *device)
5500{
Andy Hung31aca912014-03-20 17:14:59 -07005501 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005502 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005503
5504 if (!adev)
5505 return 0;
5506
5507 pthread_mutex_lock(&adev_init_lock);
5508
5509 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005510 audio_extn_snd_mon_unregister_listener(adev);
5511 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005512 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005513 audio_route_free(adev->audio_route);
5514 free(adev->snd_dev_ref_cnt);
5515 platform_deinit(adev->platform);
5516 audio_extn_extspk_deinit(adev->extspk);
5517 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005518 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005519 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5520 pcm_params_free(adev->use_case_table[i]);
5521 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005522 if (adev->adm_deinit)
5523 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005524 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005525 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005526 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005527
5528 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005530 return 0;
5531}
5532
Glenn Kasten4f993392014-05-14 07:30:48 -07005533/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5534 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5535 * just that it _might_ work.
5536 */
5537static int period_size_is_plausible_for_low_latency(int period_size)
5538{
5539 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005540 case 48:
5541 case 96:
5542 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005543 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005544 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005545 case 240:
5546 case 320:
5547 case 480:
5548 return 1;
5549 default:
5550 return 0;
5551 }
5552}
5553
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005554static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5555{
5556 int card;
5557 card_status_t status;
5558
5559 if (!parms)
5560 return;
5561
5562 if (parse_snd_card_status(parms, &card, &status) < 0)
5563 return;
5564
5565 pthread_mutex_lock(&adev->lock);
5566 bool valid_cb = (card == adev->snd_card);
5567 if (valid_cb) {
5568 if (adev->card_status != status) {
5569 adev->card_status = status;
5570 platform_snd_card_update(adev->platform, status);
5571 }
5572 }
5573 pthread_mutex_unlock(&adev->lock);
5574 return;
5575}
5576
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005577/* out and adev lock held */
5578static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5579{
5580 struct audio_usecase *uc_info;
5581 float left_p;
5582 float right_p;
5583 audio_devices_t devices;
5584
5585 uc_info = get_usecase_from_list(adev, out->usecase);
5586 if (uc_info == NULL) {
5587 ALOGE("%s: Could not find the usecase (%d) in the list",
5588 __func__, out->usecase);
5589 return -EINVAL;
5590 }
5591
5592 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5593 out->usecase, use_case_table[out->usecase]);
5594
5595 if (restore) {
5596 // restore A2DP device for active usecases and unmute if required
5597 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5598 !is_a2dp_device(uc_info->out_snd_device)) {
5599 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5600 select_devices(adev, uc_info->id);
5601 pthread_mutex_lock(&out->compr_mute_lock);
5602 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5603 (out->a2dp_compress_mute)) {
5604 out->a2dp_compress_mute = false;
5605 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5606 }
5607 pthread_mutex_unlock(&out->compr_mute_lock);
5608 }
5609 } else {
5610 // mute compress stream if suspended
5611 pthread_mutex_lock(&out->compr_mute_lock);
5612 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5613 (!out->a2dp_compress_mute)) {
5614 if (!out->standby) {
5615 ALOGD("%s: selecting speaker and muting stream", __func__);
5616 devices = out->devices;
5617 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5618 left_p = out->volume_l;
5619 right_p = out->volume_r;
5620 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5621 compress_pause(out->compr);
5622 set_compr_volume(&out->stream, 0.0f, 0.0f);
5623 out->a2dp_compress_mute = true;
5624 select_devices(adev, out->usecase);
5625 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5626 compress_resume(out->compr);
5627 out->devices = devices;
5628 out->volume_l = left_p;
5629 out->volume_r = right_p;
5630 }
5631 }
5632 pthread_mutex_unlock(&out->compr_mute_lock);
5633 }
5634 ALOGV("%s: exit", __func__);
5635 return 0;
5636}
5637
5638int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5639{
5640 int ret = 0;
5641
5642 lock_output_stream(out);
5643 pthread_mutex_lock(&adev->lock);
5644
5645 ret = check_a2dp_restore_l(adev, out, restore);
5646
5647 pthread_mutex_unlock(&adev->lock);
5648 pthread_mutex_unlock(&out->lock);
5649 return ret;
5650}
5651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005652static int adev_open(const hw_module_t *module, const char *name,
5653 hw_device_t **device)
5654{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005655 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005656
Eric Laurent2bafff12016-03-17 12:17:23 -07005657 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005658 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005659 pthread_mutex_lock(&adev_init_lock);
5660 if (audio_device_ref_count != 0) {
5661 *device = &adev->device.common;
5662 audio_device_ref_count++;
5663 ALOGV("%s: returning existing instance of adev", __func__);
5664 ALOGV("%s: exit", __func__);
5665 pthread_mutex_unlock(&adev_init_lock);
5666 return 0;
5667 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005668 adev = calloc(1, sizeof(struct audio_device));
5669
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005670 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005672 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5673 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5674 adev->device.common.module = (struct hw_module_t *)module;
5675 adev->device.common.close = adev_close;
5676
5677 adev->device.init_check = adev_init_check;
5678 adev->device.set_voice_volume = adev_set_voice_volume;
5679 adev->device.set_master_volume = adev_set_master_volume;
5680 adev->device.get_master_volume = adev_get_master_volume;
5681 adev->device.set_master_mute = adev_set_master_mute;
5682 adev->device.get_master_mute = adev_get_master_mute;
5683 adev->device.set_mode = adev_set_mode;
5684 adev->device.set_mic_mute = adev_set_mic_mute;
5685 adev->device.get_mic_mute = adev_get_mic_mute;
5686 adev->device.set_parameters = adev_set_parameters;
5687 adev->device.get_parameters = adev_get_parameters;
5688 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5689 adev->device.open_output_stream = adev_open_output_stream;
5690 adev->device.close_output_stream = adev_close_output_stream;
5691 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005693 adev->device.close_input_stream = adev_close_input_stream;
5694 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005695 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696
5697 /* Set the default route before the PCM stream is opened */
5698 pthread_mutex_lock(&adev->lock);
5699 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005700 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005702 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005703 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005704 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005705 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005706 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707 pthread_mutex_unlock(&adev->lock);
5708
5709 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005710 adev->platform = platform_init(adev);
5711 if (!adev->platform) {
5712 free(adev->snd_dev_ref_cnt);
5713 free(adev);
5714 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5715 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005716 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005717 return -EINVAL;
5718 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005719 adev->extspk = audio_extn_extspk_init(adev);
5720
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005721 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5722 if (adev->visualizer_lib == NULL) {
5723 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5724 } else {
5725 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5726 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005727 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005728 "visualizer_hal_start_output");
5729 adev->visualizer_stop_output =
5730 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5731 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005732 }
5733
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005734 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5735 if (adev->offload_effects_lib == NULL) {
5736 ALOGW("%s: DLOPEN failed for %s", __func__,
5737 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5738 } else {
5739 ALOGV("%s: DLOPEN successful for %s", __func__,
5740 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5741 adev->offload_effects_start_output =
5742 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5743 "offload_effects_bundle_hal_start_output");
5744 adev->offload_effects_stop_output =
5745 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5746 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005747 }
5748
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005749 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5750 if (adev->adm_lib == NULL) {
5751 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5752 } else {
5753 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5754 adev->adm_init = (adm_init_t)
5755 dlsym(adev->adm_lib, "adm_init");
5756 adev->adm_deinit = (adm_deinit_t)
5757 dlsym(adev->adm_lib, "adm_deinit");
5758 adev->adm_register_input_stream = (adm_register_input_stream_t)
5759 dlsym(adev->adm_lib, "adm_register_input_stream");
5760 adev->adm_register_output_stream = (adm_register_output_stream_t)
5761 dlsym(adev->adm_lib, "adm_register_output_stream");
5762 adev->adm_deregister_stream = (adm_deregister_stream_t)
5763 dlsym(adev->adm_lib, "adm_deregister_stream");
5764 adev->adm_request_focus = (adm_request_focus_t)
5765 dlsym(adev->adm_lib, "adm_request_focus");
5766 adev->adm_abandon_focus = (adm_abandon_focus_t)
5767 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005768 adev->adm_set_config = (adm_set_config_t)
5769 dlsym(adev->adm_lib, "adm_set_config");
5770 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5771 dlsym(adev->adm_lib, "adm_request_focus_v2");
5772 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5773 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5774 adev->adm_on_routing_change = (adm_on_routing_change_t)
5775 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005776 }
5777
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005778 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005779 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005781 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005782
Andy Hung31aca912014-03-20 17:14:59 -07005783 if (k_enable_extended_precision)
5784 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005785
Glenn Kasten4f993392014-05-14 07:30:48 -07005786 char value[PROPERTY_VALUE_MAX];
5787 int trial;
5788 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5789 trial = atoi(value);
5790 if (period_size_is_plausible_for_low_latency(trial)) {
5791 pcm_config_low_latency.period_size = trial;
5792 pcm_config_low_latency.start_threshold = trial / 4;
5793 pcm_config_low_latency.avail_min = trial / 4;
5794 configured_low_latency_capture_period_size = trial;
5795 }
5796 }
5797 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5798 trial = atoi(value);
5799 if (period_size_is_plausible_for_low_latency(trial)) {
5800 configured_low_latency_capture_period_size = trial;
5801 }
5802 }
5803
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005804 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5805
Eric Laurent5f4ca952018-10-19 17:33:43 -07005806 adev->camera_orientation = CAMERA_DEFAULT;
5807
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005808 // commented as full set of app type cfg is sent from platform
5809 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005810 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005811
5812 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5813 af_period_multiplier = atoi(value);
5814 if (af_period_multiplier < 0) {
5815 af_period_multiplier = 2;
5816 } else if (af_period_multiplier > 4) {
5817 af_period_multiplier = 4;
5818 }
5819 ALOGV("new period_multiplier = %d", af_period_multiplier);
5820 }
5821
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005822 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005823 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005824
vivek mehta1a9b7c02015-06-25 11:49:38 -07005825 pthread_mutex_unlock(&adev_init_lock);
5826
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005827 if (adev->adm_init)
5828 adev->adm_data = adev->adm_init();
5829
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005830 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005831 audio_extn_snd_mon_init();
5832 pthread_mutex_lock(&adev->lock);
5833 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5834 adev->card_status = CARD_STATUS_ONLINE;
5835 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005836 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005837
Eric Laurent2bafff12016-03-17 12:17:23 -07005838 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005839 return 0;
5840}
5841
5842static struct hw_module_methods_t hal_module_methods = {
5843 .open = adev_open,
5844};
5845
5846struct audio_module HAL_MODULE_INFO_SYM = {
5847 .common = {
5848 .tag = HARDWARE_MODULE_TAG,
5849 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5850 .hal_api_version = HARDWARE_HAL_API_VERSION,
5851 .id = AUDIO_HARDWARE_MODULE_ID,
5852 .name = "QCOM Audio HAL",
5853 .author = "Code Aurora Forum",
5854 .methods = &hal_module_methods,
5855 },
5856};