blob: 0e92bfe428101fdfc1d818bda4a7c4c8201f74e6 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
jiabinad481a72018-07-23 12:03:17 -0700228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
jiabinad481a72018-07-23 12:03:17 -0700242#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
Haynes Mathew George03c40102016-01-29 17:57:48 -0800543static inline bool is_mmap_usecase(audio_usecase_t uc_id)
544{
545 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
546 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
547}
548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700549static int get_snd_codec_id(audio_format_t format)
550{
551 int id = 0;
552
Eric Laurent8251ac82014-07-23 11:00:25 -0700553 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700554 case AUDIO_FORMAT_MP3:
555 id = SND_AUDIOCODEC_MP3;
556 break;
557 case AUDIO_FORMAT_AAC:
558 id = SND_AUDIOCODEC_AAC;
559 break;
560 default:
561 ALOGE("%s: Unsupported audio format", __func__);
562 }
563
564 return id;
565}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800566
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800567static int audio_ssr_status(struct audio_device *adev)
568{
569 int ret = 0;
570 struct mixer_ctl *ctl;
571 const char *mixer_ctl_name = "Audio SSR Status";
572
573 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
574 ret = mixer_ctl_get_value(ctl, 0);
575 ALOGD("%s: value: %d", __func__, ret);
576 return ret;
577}
578
vivek mehta4a824772017-06-08 19:05:49 -0700579static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
580{
581 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
582}
583
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800584static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
585{
586 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
587 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
588 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
589 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
590 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
591 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
592
593}
594
595static bool is_a2dp_device(snd_device_t out_snd_device)
596{
597 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_audio_route(struct audio_device *adev,
601 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
yixuanjiang509f0a72018-09-06 18:37:23 +0800603 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700604 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800605
606 if (usecase == NULL)
607 return -EINVAL;
608
609 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
610
yixuanjiang509f0a72018-09-06 18:37:23 +0800611 if (usecase->type == PCM_CAPTURE)
612 snd_device = usecase->in_snd_device;
613 else
614 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530615 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800616 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700617
618 // we shouldn't truncate mixer_path
619 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
620 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
621 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800622 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700623
yixuanjiang509f0a72018-09-06 18:37:23 +0800624 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700625 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700626 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800628 ALOGV("%s: exit", __func__);
629 return 0;
630}
631
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800632int disable_audio_route(struct audio_device *adev,
633 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800634{
yixuanjiang509f0a72018-09-06 18:37:23 +0800635 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700636 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800637
638 if (usecase == NULL)
639 return -EINVAL;
640
641 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800642 if (usecase->type == PCM_CAPTURE)
643 snd_device = usecase->in_snd_device;
644 else
645 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700646
647 // we shouldn't truncate mixer_path
648 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
649 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
650 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800651 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700652 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700653
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700654 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000655 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800657 ALOGV("%s: exit", __func__);
658 return 0;
659}
660
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800661int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700662 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800663{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700664 int i, num_devices = 0;
665 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800666 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800667 if (snd_device < SND_DEVICE_MIN ||
668 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800669 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800670 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700672
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700673 platform_send_audio_calibration(adev->platform, snd_device);
674
vivek mehtade4849c2016-03-03 17:23:38 -0800675 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700676 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700677 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800678 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 }
680
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700681 /* due to the possibility of calibration overwrite between listen
682 and audio, notify sound trigger hal before audio calibration is sent */
683 audio_extn_sound_trigger_update_device_status(snd_device,
684 ST_EVENT_SND_DEVICE_BUSY);
685
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 if (audio_extn_spkr_prot_is_enabled())
687 audio_extn_spkr_prot_calib_cancel(adev);
688
zhaoyang yin4211fad2015-06-04 21:13:25 +0800689 audio_extn_dsm_feedback_enable(adev, snd_device, true);
690
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700691 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800692 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800693 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
695 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700696 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800697 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700698 }
699 if (audio_extn_spkr_prot_start_processing(snd_device)) {
700 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700703 } else if (platform_can_split_snd_device(snd_device,
704 &num_devices,
705 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700706 for (i = 0; i < num_devices; i++) {
707 enable_snd_device(adev, new_snd_devices[i]);
708 }
vivek mehtab6506412015-08-07 16:55:17 -0700709 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
712 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
713 ALOGE(" %s: Invalid sound device returned", __func__);
714 goto on_error;
715 }
Ed Tam70b5c142016-03-21 19:14:29 -0700716
Eric Laurent2e140aa2016-06-30 17:14:46 -0700717 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700718
719 if (is_a2dp_device(snd_device) &&
720 (audio_extn_a2dp_start_playback() < 0)) {
721 ALOGE("%s: failed to configure A2DP control path", __func__);
722 goto on_error;
723 }
724
vivek mehtade4849c2016-03-03 17:23:38 -0800725 audio_route_apply_and_update_path(adev->audio_route, device_name);
726 }
727on_success:
728 adev->snd_dev_ref_cnt[snd_device]++;
729 ret_val = 0;
730on_error:
731 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800732}
733
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800734int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700735 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800736{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700737 int i, num_devices = 0;
738 snd_device_t new_snd_devices[2];
739
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800740 if (snd_device < SND_DEVICE_MIN ||
741 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800742 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800743 return -EINVAL;
744 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700745 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
746 ALOGE("%s: device ref cnt is already 0", __func__);
747 return -EINVAL;
748 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800749 audio_extn_tfa_98xx_disable_speaker(snd_device);
750
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700751 adev->snd_dev_ref_cnt[snd_device]--;
752 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800753 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800754
755 if (is_a2dp_device(snd_device))
756 audio_extn_a2dp_stop_playback();
757
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700758 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800759 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700760 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700761 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
762 audio_extn_spkr_prot_is_enabled()) {
763 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700764
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700765 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
766 // and does not use speaker swap. As this code causes a problem with device enable ref
767 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700768 // when speaker device is disabled, reset swap.
769 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700770 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700771
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700772 } else if (platform_can_split_snd_device(snd_device,
773 &num_devices,
774 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700775 for (i = 0; i < num_devices; i++) {
776 disable_snd_device(adev, new_snd_devices[i]);
777 }
vivek mehtab6506412015-08-07 16:55:17 -0700778 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700779 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800780 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
781 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
782 ALOGE(" %s: Invalid sound device returned", __func__);
783 return -EINVAL;
784 }
785
Eric Laurent2e140aa2016-06-30 17:14:46 -0700786 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800787 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700788 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700789 audio_extn_sound_trigger_update_device_status(snd_device,
790 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800793 return 0;
794}
795
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700796/*
797 legend:
798 uc - existing usecase
799 new_uc - new usecase
800 d1, d11, d2 - SND_DEVICE enums
801 a1, a2 - corresponding ANDROID device enums
802 B, B1, B2 - backend strings
803
804case 1
805 uc->dev d1 (a1) B1
806 new_uc->dev d1 (a1), d2 (a2) B1, B2
807
808 resolution: disable and enable uc->dev on d1
809
810case 2
811 uc->dev d1 (a1) B1
812 new_uc->dev d11 (a1) B1
813
814 resolution: need to switch uc since d1 and d11 are related
815 (e.g. speaker and voice-speaker)
816 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
817
818case 3
819 uc->dev d1 (a1) B1
820 new_uc->dev d2 (a2) B2
821
822 resolution: no need to switch uc
823
824case 4
825 uc->dev d1 (a1) B
826 new_uc->dev d2 (a2) B
827
828 resolution: disable enable uc-dev on d2 since backends match
829 we cannot enable two streams on two different devices if they
830 share the same backend. e.g. if offload is on speaker device using
831 QUAD_MI2S backend and a low-latency stream is started on voice-handset
832 using the same backend, offload must also be switched to voice-handset.
833
834case 5
835 uc->dev d1 (a1) B
836 new_uc->dev d1 (a1), d2 (a2) B
837
838 resolution: disable enable uc-dev on d2 since backends match
839 we cannot enable two streams on two different devices if they
840 share the same backend.
841
842case 6
843 uc->dev d1 a1 B1
844 new_uc->dev d2 a1 B2
845
846 resolution: no need to switch
847
848case 7
849
850 uc->dev d1 (a1), d2 (a2) B1, B2
851 new_uc->dev d1 B1
852
853 resolution: no need to switch
854
855*/
856static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
857 struct audio_usecase *new_uc,
858 snd_device_t new_snd_device)
859{
860 audio_devices_t a1 = uc->stream.out->devices;
861 audio_devices_t a2 = new_uc->stream.out->devices;
862
863 snd_device_t d1 = uc->out_snd_device;
864 snd_device_t d2 = new_snd_device;
865
866 // Treat as a special case when a1 and a2 are not disjoint
867 if ((a1 != a2) && (a1 & a2)) {
868 snd_device_t d3[2];
869 int num_devices = 0;
870 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
871 &num_devices,
872 d3);
873 if (ret < 0) {
874 if (ret != -ENOSYS) {
875 ALOGW("%s failed to split snd_device %d",
876 __func__,
877 popcount(a1) > 1 ? d1 : d2);
878 }
879 goto end;
880 }
881
882 // NB: case 7 is hypothetical and isn't a practical usecase yet.
883 // But if it does happen, we need to give priority to d2 if
884 // the combo devices active on the existing usecase share a backend.
885 // This is because we cannot have a usecase active on a combo device
886 // and a new usecase requests one device in this combo pair.
887 if (platform_check_backends_match(d3[0], d3[1])) {
888 return d2; // case 5
889 } else {
890 return d1; // case 1
891 }
892 } else {
893 if (platform_check_backends_match(d1, d2)) {
894 return d2; // case 2, 4
895 } else {
896 return d1; // case 6, 3
897 }
898 }
899
900end:
901 return d2; // return whatever was calculated before.
902}
903
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700904static void check_and_route_playback_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700913 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
914 uc_info,
915 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700916
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800917 /* For a2dp device reconfigure all active sessions
918 * with new AFE encoder format based on a2dp state
919 */
920 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -0700921 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
922 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800923 audio_extn_a2dp_is_force_device_switch()) {
924 force_routing = true;
925 }
926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 /*
928 * This function is to make sure that all the usecases that are active on
929 * the hardware codec backend are always routed to any one device that is
930 * handled by the hardware codec.
931 * For example, if low-latency and deep-buffer usecases are currently active
932 * on speaker and out_set_parameters(headset) is received on low-latency
933 * output, then we have to make sure deep-buffer is also switched to headset,
934 * because of the limitation that both the devices cannot be enabled
935 * at the same time as they share the same backend.
936 */
937 /* Disable all the usecases on the shared backend other than the
938 specified usecase */
939 for (i = 0; i < AUDIO_USECASE_MAX; i++)
940 switch_device[i] = false;
941
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700944 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
945 continue;
946
947 if (force_routing ||
948 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700949 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
950 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700951 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700952 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
953 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 switch_device[usecase->id] = true;
957 num_uc_to_switch++;
958 }
959 }
960
961 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700962 list_for_each(node, &adev->usecase_list) {
963 usecase = node_to_item(node, struct audio_usecase, list);
964 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900966 }
967 }
968
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700969 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900970 list_for_each(node, &adev->usecase_list) {
971 usecase = node_to_item(node, struct audio_usecase, list);
972 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700973 d_device = derive_playback_snd_device(usecase, uc_info,
974 snd_device);
975 enable_snd_device(adev, d_device);
976 /* Update the out_snd_device before enabling the audio route */
977 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700978 }
979 }
980
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981 /* Re-route all the usecases on the shared backend other than the
982 specified usecase to new snd devices */
983 list_for_each(node, &adev->usecase_list) {
984 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700986 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700987 }
988 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700989 }
990}
991
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700992static void check_and_route_capture_usecases(struct audio_device *adev,
993 struct audio_usecase *uc_info,
994 snd_device_t snd_device)
995{
996 struct listnode *node;
997 struct audio_usecase *usecase;
998 bool switch_device[AUDIO_USECASE_MAX];
999 int i, num_uc_to_switch = 0;
1000
vivek mehta4ed66e62016-04-15 23:33:34 -07001001 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1002
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /*
1004 * This function is to make sure that all the active capture usecases
1005 * are always routed to the same input sound device.
1006 * For example, if audio-record and voice-call usecases are currently
1007 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1008 * is received for voice call then we have to make sure that audio-record
1009 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1010 * because of the limitation that two devices cannot be enabled
1011 * at the same time if they share the same backend.
1012 */
1013 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1014 switch_device[i] = false;
1015
1016 list_for_each(node, &adev->usecase_list) {
1017 usecase = node_to_item(node, struct audio_usecase, list);
1018 if (usecase->type != PCM_PLAYBACK &&
1019 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001020 usecase->in_snd_device != snd_device &&
1021 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001022 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1023 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001024 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001025 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001026 switch_device[usecase->id] = true;
1027 num_uc_to_switch++;
1028 }
1029 }
1030
1031 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001032 list_for_each(node, &adev->usecase_list) {
1033 usecase = node_to_item(node, struct audio_usecase, list);
1034 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001035 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001036 }
1037 }
1038
1039 list_for_each(node, &adev->usecase_list) {
1040 usecase = node_to_item(node, struct audio_usecase, list);
1041 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001042 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001043 }
1044 }
1045
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001046 /* Re-route all the usecases on the shared backend other than the
1047 specified usecase to new snd devices */
1048 list_for_each(node, &adev->usecase_list) {
1049 usecase = node_to_item(node, struct audio_usecase, list);
1050 /* Update the in_snd_device only before enabling the audio route */
1051 if (switch_device[usecase->id] ) {
1052 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001053 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001054 }
1055 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001056 }
1057}
1058
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001060static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001062 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001063 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001064
1065 switch (channels) {
1066 /*
1067 * Do not handle stereo output in Multi-channel cases
1068 * Stereo case is handled in normal playback path
1069 */
1070 case 6:
1071 ALOGV("%s: HDMI supports 5.1", __func__);
1072 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1073 break;
1074 case 8:
1075 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1076 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1077 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1078 break;
1079 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001080 ALOGE("HDMI does not support multi channel playback");
1081 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001082 break;
1083 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001084 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001085}
1086
Andy Hung18859412017-08-09 11:47:21 -07001087static ssize_t read_usb_sup_sample_rates(bool is_playback,
1088 uint32_t *supported_sample_rates,
1089 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001090{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001091 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1092 supported_sample_rates,
1093 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001094#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 for (ssize_t i=0; i<count; i++) {
1096 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1097 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001098 }
1099#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001100 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001101}
1102
Haynes Mathew George569b7482017-05-08 14:44:27 -07001103static int read_usb_sup_channel_masks(bool is_playback,
1104 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001105 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001106{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001108 int channel_count;
1109 uint32_t num_masks = 0;
1110 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1111 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001112 }
Eric Laurent74b55762017-07-09 17:04:53 -07001113 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001114 // start from 2 channels as framework currently doesn't support mono.
1115 // TODO: consider only supporting channel index masks beyond stereo here.
1116 for (channel_count = FCC_2;
1117 channel_count <= channels && num_masks < max_masks;
1118 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001119 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1120 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001121 for (channel_count = FCC_2;
1122 channel_count <= channels && num_masks < max_masks;
1123 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001124 supported_channel_masks[num_masks++] =
1125 audio_channel_mask_for_index_assignment_from_count(channel_count);
1126 }
1127 } else {
1128 // For capture we report all supported channel masks from 1 channel up.
1129 channel_count = MIN_CHANNEL_COUNT;
1130 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1131 // indexed mask
1132 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001133 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001134 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001135 supported_channel_masks[num_masks++] = mask;
1136 const audio_channel_mask_t index_mask =
1137 audio_channel_mask_for_index_assignment_from_count(channel_count);
1138 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1139 supported_channel_masks[num_masks++] = index_mask;
1140 }
Eric Laurent74b55762017-07-09 17:04:53 -07001141 }
1142 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001143#ifdef NDEBUG
1144 for (size_t i = 0; i < num_masks; ++i) {
1145 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1146 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1147 }
1148#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001149 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001150}
1151
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001152static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001153 audio_format_t *supported_formats,
1154 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001155{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001156 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001157 switch (bitwidth) {
1158 case 24:
1159 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001160 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001161 break;
1162 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001163 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001164 break;
1165 case 16:
1166 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001167 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001168 break;
1169 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001170 ALOGV("%s: %s supported format %d", __func__,
1171 is_playback ? "P" : "C", bitwidth);
1172 return 1;
1173}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001174
Haynes Mathew George569b7482017-05-08 14:44:27 -07001175static int read_usb_sup_params_and_compare(bool is_playback,
1176 audio_format_t *format,
1177 audio_format_t *supported_formats,
1178 uint32_t max_formats,
1179 audio_channel_mask_t *mask,
1180 audio_channel_mask_t *supported_channel_masks,
1181 uint32_t max_masks,
1182 uint32_t *rate,
1183 uint32_t *supported_sample_rates,
1184 uint32_t max_rates) {
1185 int ret = 0;
1186 int num_formats;
1187 int num_masks;
1188 int num_rates;
1189 int i;
1190
1191 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1192 max_formats);
1193 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1194 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001195
Haynes Mathew George569b7482017-05-08 14:44:27 -07001196 num_rates = read_usb_sup_sample_rates(is_playback,
1197 supported_sample_rates, max_rates);
1198
1199#define LUT(table, len, what, dflt) \
1200 for (i=0; i<len && (table[i] != what); i++); \
1201 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1202
1203 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1204 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1205 LUT(supported_sample_rates, num_rates, *rate, 0);
1206
1207#undef LUT
1208 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001209}
1210
Andy Hungd9653bd2017-08-01 19:31:39 -07001211static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1212{
1213 // Check if usb is ready.
1214 // The usb device may have been removed quickly after insertion and hence
1215 // no longer available. This will show up as empty channel masks, or rates.
1216
1217 pthread_mutex_lock(&adev->lock);
1218 uint32_t supported_sample_rate;
1219
1220 // we consider usb ready if we can fetch at least one sample rate.
1221 const bool ready = read_usb_sup_sample_rates(
1222 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1223 pthread_mutex_unlock(&adev->lock);
1224 return ready;
1225}
1226
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001227static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1228{
1229 struct audio_usecase *usecase;
1230 struct listnode *node;
1231
1232 list_for_each(node, &adev->usecase_list) {
1233 usecase = node_to_item(node, struct audio_usecase, list);
1234 if (usecase->type == VOICE_CALL) {
1235 ALOGV("%s: usecase id %d", __func__, usecase->id);
1236 return usecase->id;
1237 }
1238 }
1239 return USECASE_INVALID;
1240}
1241
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001242struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1243 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244{
1245 struct audio_usecase *usecase;
1246 struct listnode *node;
1247
1248 list_for_each(node, &adev->usecase_list) {
1249 usecase = node_to_item(node, struct audio_usecase, list);
1250 if (usecase->id == uc_id)
1251 return usecase;
1252 }
1253 return NULL;
1254}
1255
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001256static bool force_device_switch(struct audio_usecase *usecase)
1257{
1258 if (usecase->stream.out == NULL) {
1259 ALOGE("%s: stream.out is NULL", __func__);
1260 return false;
1261 }
1262
1263 // Force all A2DP output devices to reconfigure for proper AFE encode format
1264 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1265 // in suspended state, hence try to trigger a retry when we again get a routing request.
1266 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1267 audio_extn_a2dp_is_force_device_switch()) {
1268 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1269 return true;
1270 }
1271
1272 return false;
1273}
1274
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001275int select_devices(struct audio_device *adev,
1276 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001278 snd_device_t out_snd_device = SND_DEVICE_NONE;
1279 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 struct audio_usecase *usecase = NULL;
1281 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001282 struct audio_usecase *hfp_usecase = NULL;
1283 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001284 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001285 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001286 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1287 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 usecase = get_usecase_from_list(adev, uc_id);
1290 if (usecase == NULL) {
1291 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1292 return -EINVAL;
1293 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001294
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001295 if ((usecase->type == VOICE_CALL) ||
1296 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001297 out_snd_device = platform_get_output_snd_device(adev->platform,
1298 usecase->stream.out->devices);
1299 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001300 usecase->devices = usecase->stream.out->devices;
1301 } else {
1302 /*
1303 * If the voice call is active, use the sound devices of voice call usecase
1304 * so that it would not result any device switch. All the usecases will
1305 * be switched to new device when select_devices() is called for voice call
1306 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001307 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001309 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001310 vc_usecase = get_usecase_from_list(adev,
1311 get_voice_usecase_id_from_list(adev));
1312 if ((vc_usecase != NULL) &&
1313 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1314 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 in_snd_device = vc_usecase->in_snd_device;
1316 out_snd_device = vc_usecase->out_snd_device;
1317 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001318 } else if (audio_extn_hfp_is_active(adev)) {
1319 hfp_ucid = audio_extn_hfp_get_usecase();
1320 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1321 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1322 in_snd_device = hfp_usecase->in_snd_device;
1323 out_snd_device = hfp_usecase->out_snd_device;
1324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 }
1326 if (usecase->type == PCM_PLAYBACK) {
1327 usecase->devices = usecase->stream.out->devices;
1328 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001329 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001330 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001331
Eric Laurentb23d5282013-05-14 15:27:20 -07001332 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001333 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001334
1335 if (voip_usecase)
1336 voip_out = voip_usecase->stream.out;
1337
1338 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001339 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001340 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001341 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001342 select_devices(adev, adev->active_input->usecase);
1343 }
1344 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001345 } else if (usecase->type == PCM_CAPTURE) {
1346 usecase->devices = usecase->stream.in->device;
1347 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001348 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001349 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001350 if (adev->active_input &&
1351 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1352 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001353
1354 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1355 USECASE_AUDIO_PLAYBACK_VOIP);
1356
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001357 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001358 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1359 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001360 } else if (voip_usecase) {
1361 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001362 } else if (adev->primary_output) {
1363 out_device = adev->primary_output->devices;
1364 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001365 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001366 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001368 }
1369 }
1370
1371 if (out_snd_device == usecase->out_snd_device &&
1372 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001373 if (!force_device_switch(usecase))
1374 return 0;
1375 }
1376
1377 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1378 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1379 return 0;
1380 }
1381
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001382 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1383 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001384 (!audio_extn_a2dp_is_ready())) {
1385 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001386 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1387 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1388 else
1389 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001390 }
1391
juyuchen66c4ecf2018-08-06 15:39:34 +08001392 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1393 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1394 }
1395
Eric Laurent2bafff12016-03-17 12:17:23 -07001396 if (out_snd_device != SND_DEVICE_NONE &&
1397 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1398 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1399 __func__,
1400 use_case_table[uc_id],
1401 adev->last_logged_snd_device[uc_id][0],
1402 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1403 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1404 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1405 -1,
1406 out_snd_device,
1407 platform_get_snd_device_name(out_snd_device),
1408 platform_get_snd_device_acdb_id(out_snd_device));
1409 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1410 }
1411 if (in_snd_device != SND_DEVICE_NONE &&
1412 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1413 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1414 __func__,
1415 use_case_table[uc_id],
1416 adev->last_logged_snd_device[uc_id][1],
1417 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1418 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1419 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1420 -1,
1421 in_snd_device,
1422 platform_get_snd_device_name(in_snd_device),
1423 platform_get_snd_device_acdb_id(in_snd_device));
1424 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1425 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001427 /*
1428 * Limitation: While in call, to do a device switch we need to disable
1429 * and enable both RX and TX devices though one of them is same as current
1430 * device.
1431 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001432 if ((usecase->type == VOICE_CALL) &&
1433 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1434 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001435 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001436 /* Disable sidetone only if voice call already exists */
1437 if (voice_is_call_state_active(adev))
1438 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001439 }
1440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001441 /* Disable current sound devices */
1442 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001443 disable_audio_route(adev, usecase);
1444 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001445 }
1446
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001447 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001448 disable_audio_route(adev, usecase);
1449 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 }
1451
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001452 /* Applicable only on the targets that has external modem.
1453 * New device information should be sent to modem before enabling
1454 * the devices to reduce in-call device switch time.
1455 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001456 if ((usecase->type == VOICE_CALL) &&
1457 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1458 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001459 status = platform_switch_voice_call_enable_device_config(adev->platform,
1460 out_snd_device,
1461 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001462 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001463
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 /* Enable new sound devices */
1465 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001466 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001467 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1468 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001469 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001470 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471 }
1472
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001473 if (in_snd_device != SND_DEVICE_NONE) {
1474 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001475 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001476 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477
Eric Laurentb23d5282013-05-14 15:27:20 -07001478 if (usecase->type == VOICE_CALL)
1479 status = platform_switch_voice_call_device_post(adev->platform,
1480 out_snd_device,
1481 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001482
sangwoo170731f2013-06-08 15:36:36 +09001483 usecase->in_snd_device = in_snd_device;
1484 usecase->out_snd_device = out_snd_device;
1485
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001486 audio_extn_tfa_98xx_set_mode();
1487
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001488 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001489
Jasmine Cha70771b62018-05-15 15:02:43 +08001490 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001491
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001492 /* Applicable only on the targets that has external modem.
1493 * Enable device command should be sent to modem only after
1494 * enabling voice call mixer controls
1495 */
vivek mehta765eb642015-08-07 19:46:06 -07001496 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001497 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1498 out_snd_device,
1499 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001500 /* Enable sidetone only if voice call already exists */
1501 if (voice_is_call_state_active(adev))
1502 voice_set_sidetone(adev, out_snd_device, true);
1503 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001504
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001505 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001506 struct stream_out *voip_out = voip_usecase->stream.out;
1507 audio_extn_utils_send_app_type_gain(adev,
1508 voip_out->app_type_cfg.app_type,
1509 &voip_out->app_type_cfg.gain[0]);
1510 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001511 return status;
1512}
1513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514static int stop_input_stream(struct stream_in *in)
1515{
1516 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 struct audio_usecase *uc_info;
1518 struct audio_device *adev = in->dev;
1519
Eric Laurent994a6932013-07-17 11:51:42 -07001520 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001522
1523 if (adev->active_input) {
1524 if (adev->active_input->usecase == in->usecase) {
1525 adev->active_input = NULL;
1526 } else {
1527 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1528 __func__,
1529 use_case_table[adev->active_input->usecase],
1530 use_case_table[in->usecase]);
1531 }
1532 }
1533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 uc_info = get_usecase_from_list(adev, in->usecase);
1535 if (uc_info == NULL) {
1536 ALOGE("%s: Could not find the usecase (%d) in the list",
1537 __func__, in->usecase);
1538 return -EINVAL;
1539 }
1540
vivek mehta781065c2017-04-04 12:55:01 -07001541 /* Close in-call recording streams */
1542 voice_check_and_stop_incall_rec_usecase(adev, in);
1543
Eric Laurent150dbfe2013-02-27 14:31:02 -08001544 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001545 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546
1547 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001548 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001550 list_remove(&uc_info->list);
1551 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552
Eric Laurent994a6932013-07-17 11:51:42 -07001553 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554 return ret;
1555}
1556
1557int start_input_stream(struct stream_in *in)
1558{
1559 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001560 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561 struct audio_usecase *uc_info;
1562 struct audio_device *adev = in->dev;
1563
Eric Laurent994a6932013-07-17 11:51:42 -07001564 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001565
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001566 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1567 return -EIO;
1568
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001569 if (in->card_status == CARD_STATUS_OFFLINE ||
1570 adev->card_status == CARD_STATUS_OFFLINE) {
1571 ALOGW("in->card_status or adev->card_status offline, try again");
1572 ret = -EAGAIN;
1573 goto error_config;
1574 }
1575
vivek mehta781065c2017-04-04 12:55:01 -07001576 /* Check if source matches incall recording usecase criteria */
1577 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1578 if (ret)
1579 goto error_config;
1580 else
1581 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1582
Eric Laurentb23d5282013-05-14 15:27:20 -07001583 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584 if (in->pcm_device_id < 0) {
1585 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1586 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001587 ret = -EINVAL;
1588 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001590
1591 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1593 uc_info->id = in->usecase;
1594 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001595 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001596 uc_info->devices = in->device;
1597 uc_info->in_snd_device = SND_DEVICE_NONE;
1598 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001600 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001601
Wei Wangf4837d52017-11-21 14:51:20 -08001602 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001603 audio_extn_perf_lock_acquire();
1604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606
Eric Laurent0e46adf2016-12-16 12:49:24 -08001607 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001608 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001609 ALOGE("%s: pcm stream not ready", __func__);
1610 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001611 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001612 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001613 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001614 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1615 goto error_open;
1616 }
1617 } else {
1618 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1619 unsigned int pcm_open_retry_count = 0;
1620
1621 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1622 flags |= PCM_MMAP | PCM_NOIRQ;
1623 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1624 } else if (in->realtime) {
1625 flags |= PCM_MMAP | PCM_NOIRQ;
1626 }
1627
1628 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1629 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1630
1631 while (1) {
1632 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1633 flags, &in->config);
1634 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1635 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1636 if (in->pcm != NULL) {
1637 pcm_close(in->pcm);
1638 in->pcm = NULL;
1639 }
1640 if (pcm_open_retry_count-- == 0) {
1641 ret = -EIO;
1642 goto error_open;
1643 }
1644 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1645 continue;
1646 }
1647 break;
1648 }
1649
1650 ALOGV("%s: pcm_prepare", __func__);
1651 ret = pcm_prepare(in->pcm);
1652 if (ret < 0) {
1653 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001654 pcm_close(in->pcm);
1655 in->pcm = NULL;
1656 goto error_open;
1657 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001658 if (in->realtime) {
1659 ret = pcm_start(in->pcm);
1660 if (ret < 0) {
1661 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1662 pcm_close(in->pcm);
1663 in->pcm = NULL;
1664 goto error_open;
1665 }
1666 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001667 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001668 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001669 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001670 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001671 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001672
Eric Laurent0e46adf2016-12-16 12:49:24 -08001673 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001674
1675error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001677 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001678 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001679
1680error_config:
1681 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001682 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001683 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684}
1685
Eric Laurenta1478072015-09-21 17:21:52 -07001686void lock_input_stream(struct stream_in *in)
1687{
1688 pthread_mutex_lock(&in->pre_lock);
1689 pthread_mutex_lock(&in->lock);
1690 pthread_mutex_unlock(&in->pre_lock);
1691}
1692
1693void lock_output_stream(struct stream_out *out)
1694{
1695 pthread_mutex_lock(&out->pre_lock);
1696 pthread_mutex_lock(&out->lock);
1697 pthread_mutex_unlock(&out->pre_lock);
1698}
1699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700/* must be called with out->lock locked */
1701static int send_offload_cmd_l(struct stream_out* out, int command)
1702{
1703 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1704
1705 ALOGVV("%s %d", __func__, command);
1706
1707 cmd->cmd = command;
1708 list_add_tail(&out->offload_cmd_list, &cmd->node);
1709 pthread_cond_signal(&out->offload_cond);
1710 return 0;
1711}
1712
1713/* must be called iwth out->lock locked */
1714static void stop_compressed_output_l(struct stream_out *out)
1715{
1716 out->offload_state = OFFLOAD_STATE_IDLE;
1717 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001718 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 if (out->compr != NULL) {
1720 compress_stop(out->compr);
1721 while (out->offload_thread_blocked) {
1722 pthread_cond_wait(&out->cond, &out->lock);
1723 }
1724 }
1725}
1726
1727static void *offload_thread_loop(void *context)
1728{
1729 struct stream_out *out = (struct stream_out *) context;
1730 struct listnode *item;
1731
1732 out->offload_state = OFFLOAD_STATE_IDLE;
1733 out->playback_started = 0;
1734
1735 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1736 set_sched_policy(0, SP_FOREGROUND);
1737 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1738
1739 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001740 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741 for (;;) {
1742 struct offload_cmd *cmd = NULL;
1743 stream_callback_event_t event;
1744 bool send_callback = false;
1745
1746 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1747 __func__, list_empty(&out->offload_cmd_list),
1748 out->offload_state);
1749 if (list_empty(&out->offload_cmd_list)) {
1750 ALOGV("%s SLEEPING", __func__);
1751 pthread_cond_wait(&out->offload_cond, &out->lock);
1752 ALOGV("%s RUNNING", __func__);
1753 continue;
1754 }
1755
1756 item = list_head(&out->offload_cmd_list);
1757 cmd = node_to_item(item, struct offload_cmd, node);
1758 list_remove(item);
1759
1760 ALOGVV("%s STATE %d CMD %d out->compr %p",
1761 __func__, out->offload_state, cmd->cmd, out->compr);
1762
1763 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1764 free(cmd);
1765 break;
1766 }
1767
1768 if (out->compr == NULL) {
1769 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001770 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 pthread_cond_signal(&out->cond);
1772 continue;
1773 }
1774 out->offload_thread_blocked = true;
1775 pthread_mutex_unlock(&out->lock);
1776 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001777 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1779 compress_wait(out->compr, -1);
1780 send_callback = true;
1781 event = STREAM_CBK_EVENT_WRITE_READY;
1782 break;
1783 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001784 compress_next_track(out->compr);
1785 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786 send_callback = true;
1787 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001788 /* Resend the metadata for next iteration */
1789 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001790 break;
1791 case OFFLOAD_CMD_DRAIN:
1792 compress_drain(out->compr);
1793 send_callback = true;
1794 event = STREAM_CBK_EVENT_DRAIN_READY;
1795 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001796 case OFFLOAD_CMD_ERROR:
1797 send_callback = true;
1798 event = STREAM_CBK_EVENT_ERROR;
1799 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 default:
1801 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1802 break;
1803 }
Eric Laurenta1478072015-09-21 17:21:52 -07001804 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 out->offload_thread_blocked = false;
1806 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001807 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001808 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001809 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001810 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001811 free(cmd);
1812 }
1813
1814 pthread_cond_signal(&out->cond);
1815 while (!list_empty(&out->offload_cmd_list)) {
1816 item = list_head(&out->offload_cmd_list);
1817 list_remove(item);
1818 free(node_to_item(item, struct offload_cmd, node));
1819 }
1820 pthread_mutex_unlock(&out->lock);
1821
1822 return NULL;
1823}
1824
1825static int create_offload_callback_thread(struct stream_out *out)
1826{
1827 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1828 list_init(&out->offload_cmd_list);
1829 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1830 offload_thread_loop, out);
1831 return 0;
1832}
1833
1834static int destroy_offload_callback_thread(struct stream_out *out)
1835{
Eric Laurenta1478072015-09-21 17:21:52 -07001836 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001837 stop_compressed_output_l(out);
1838 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1839
1840 pthread_mutex_unlock(&out->lock);
1841 pthread_join(out->offload_thread, (void **) NULL);
1842 pthread_cond_destroy(&out->offload_cond);
1843
1844 return 0;
1845}
1846
Eric Laurent07eeafd2013-10-06 12:52:49 -07001847static bool allow_hdmi_channel_config(struct audio_device *adev)
1848{
1849 struct listnode *node;
1850 struct audio_usecase *usecase;
1851 bool ret = true;
1852
1853 list_for_each(node, &adev->usecase_list) {
1854 usecase = node_to_item(node, struct audio_usecase, list);
1855 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1856 /*
1857 * If voice call is already existing, do not proceed further to avoid
1858 * disabling/enabling both RX and TX devices, CSD calls, etc.
1859 * Once the voice call done, the HDMI channels can be configured to
1860 * max channels of remaining use cases.
1861 */
1862 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001863 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001864 __func__);
1865 ret = false;
1866 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001867 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1868 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001869 "no change in HDMI channels", __func__);
1870 ret = false;
1871 break;
1872 }
1873 }
1874 }
1875 return ret;
1876}
1877
1878static int check_and_set_hdmi_channels(struct audio_device *adev,
1879 unsigned int channels)
1880{
1881 struct listnode *node;
1882 struct audio_usecase *usecase;
1883
1884 /* Check if change in HDMI channel config is allowed */
1885 if (!allow_hdmi_channel_config(adev))
1886 return 0;
1887
1888 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001889 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001890 return 0;
1891 }
1892
1893 platform_set_hdmi_channels(adev->platform, channels);
1894 adev->cur_hdmi_channels = channels;
1895
1896 /*
1897 * Deroute all the playback streams routed to HDMI so that
1898 * the back end is deactivated. Note that backend will not
1899 * be deactivated if any one stream is connected to it.
1900 */
1901 list_for_each(node, &adev->usecase_list) {
1902 usecase = node_to_item(node, struct audio_usecase, list);
1903 if (usecase->type == PCM_PLAYBACK &&
1904 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001905 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001906 }
1907 }
1908
1909 /*
1910 * Enable all the streams disabled above. Now the HDMI backend
1911 * will be activated with new channel configuration
1912 */
1913 list_for_each(node, &adev->usecase_list) {
1914 usecase = node_to_item(node, struct audio_usecase, list);
1915 if (usecase->type == PCM_PLAYBACK &&
1916 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001917 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001918 }
1919 }
1920
1921 return 0;
1922}
1923
Haynes Mathew George65f6b432018-02-27 17:44:55 -08001924static int check_and_set_usb_service_interval(struct audio_device *adev,
1925 struct audio_usecase *uc_info,
1926 bool min)
1927{
1928 struct listnode *node;
1929 struct audio_usecase *usecase;
1930 bool switch_usecases = false;
1931 bool reconfig = false;
1932
1933 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
1934 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
1935 return -1;
1936
1937 /* set if the valid usecase do not already exist */
1938 list_for_each(node, &adev->usecase_list) {
1939 usecase = node_to_item(node, struct audio_usecase, list);
1940 if (usecase->type == PCM_PLAYBACK &&
1941 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
1942 switch (usecase->id) {
1943 case USECASE_AUDIO_PLAYBACK_MMAP:
1944 case USECASE_AUDIO_PLAYBACK_ULL:
1945 // cannot reconfig while mmap/ull is present.
1946 return -1;
1947 default:
1948 switch_usecases = true;
1949 break;
1950 }
1951 }
1952 if (switch_usecases)
1953 break;
1954 }
1955 /*
1956 * client can try to set service interval in start_output_stream
1957 * to min or to 0 (i.e reset) in stop_output_stream .
1958 */
1959 unsigned long service_interval =
1960 audio_extn_usb_find_service_interval(min, true /*playback*/);
1961 int ret = platform_set_usb_service_interval(adev->platform,
1962 true /*playback*/,
1963 service_interval,
1964 &reconfig);
1965 /* no change or not supported or no active usecases */
1966 if (ret || !reconfig || !switch_usecases)
1967 return -1;
1968 return 0;
1969#undef VALID_USECASE
1970}
1971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972static int stop_output_stream(struct stream_out *out)
1973{
1974 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975 struct audio_usecase *uc_info;
1976 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08001977 bool has_voip_usecase =
1978 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979
Eric Laurent994a6932013-07-17 11:51:42 -07001980 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 uc_info = get_usecase_from_list(adev, out->usecase);
1983 if (uc_info == NULL) {
1984 ALOGE("%s: Could not find the usecase (%d) in the list",
1985 __func__, out->usecase);
1986 return -EINVAL;
1987 }
1988
Haynes Mathew George41f86652014-06-17 14:22:15 -07001989 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1990 if (adev->visualizer_stop_output != NULL)
1991 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1992 if (adev->offload_effects_stop_output != NULL)
1993 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001994 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1995 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1996 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001997 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001998
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07001999 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2000 voice_set_device_mute_flag(adev, false);
2001
Eric Laurent150dbfe2013-02-27 14:31:02 -08002002 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002003 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004
2005 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002006 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002008 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009
Eric Laurent0499d4f2014-08-25 22:39:29 -05002010 audio_extn_extspk_update(adev->extspk);
2011
Eric Laurent07eeafd2013-10-06 12:52:49 -07002012 /* Must be called after removing the usecase from list */
2013 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2014 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002015 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002016 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2017 if (ret == 0) {
2018 /* default service interval was successfully updated,
2019 reopen USB backend with new service interval */
2020 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2021 }
2022 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002023 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002024
HW Lee88512e92018-06-12 15:26:09 +08002025 if (has_voip_usecase ||
2026 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2027 struct listnode *node;
2028 struct audio_usecase *usecase;
2029 list_for_each(node, &adev->usecase_list) {
2030 usecase = node_to_item(node, struct audio_usecase, list);
2031 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2032 continue;
2033
2034 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2035 __func__, usecase->id, use_case_table[usecase->id],
2036 out->usecase, use_case_table[out->usecase]);
2037 select_devices(adev, usecase->id);
2038 }
2039 }
2040
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002041 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002042 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043 return ret;
2044}
2045
2046int start_output_stream(struct stream_out *out)
2047{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 struct audio_usecase *uc_info;
2050 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002051 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052
Eric Laurent994a6932013-07-17 11:51:42 -07002053 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002055
2056 if (out->card_status == CARD_STATUS_OFFLINE ||
2057 adev->card_status == CARD_STATUS_OFFLINE) {
2058 ALOGW("out->card_status or adev->card_status offline, try again");
2059 ret = -EAGAIN;
2060 goto error_config;
2061 }
2062
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002063 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2064 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002065 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002066 a2dp_combo = true;
2067 } else {
2068 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2069 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2070 ret = -EAGAIN;
2071 goto error_config;
2072 }
2073 }
2074 }
2075 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002076 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 if (out->pcm_device_id < 0) {
2078 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2079 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002080 ret = -EINVAL;
2081 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 }
2083
2084 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2085 uc_info->id = out->usecase;
2086 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002087 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002088 uc_info->devices = out->devices;
2089 uc_info->in_snd_device = SND_DEVICE_NONE;
2090 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002091
Eric Laurent07eeafd2013-10-06 12:52:49 -07002092 /* This must be called before adding this usecase to the list */
2093 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2094 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002095 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2096 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2097 /* USB backend is not reopened immediately.
2098 This is eventually done as part of select_devices */
2099 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002100
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002101 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102
Wei Wangf4837d52017-11-21 14:51:20 -08002103 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002104 audio_extn_perf_lock_acquire();
2105
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002106 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2107 (!audio_extn_a2dp_is_ready())) {
2108 if (!a2dp_combo) {
2109 check_a2dp_restore_l(adev, out, false);
2110 } else {
2111 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002112 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2113 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2114 else
2115 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002116 select_devices(adev, out->usecase);
2117 out->devices = dev;
2118 }
2119 } else {
2120 select_devices(adev, out->usecase);
2121 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002122
Eric Laurent0499d4f2014-08-25 22:39:29 -05002123 audio_extn_extspk_update(adev->extspk);
2124
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002125 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2126 voice_set_device_mute_flag(adev, true);
2127
Andy Hung31aca912014-03-20 17:14:59 -07002128 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002129 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002130 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2131 out->pcm = NULL;
2132 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2133 COMPRESS_IN, &out->compr_config);
2134 if (out->compr && !is_compress_ready(out->compr)) {
2135 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2136 compress_close(out->compr);
2137 out->compr = NULL;
2138 ret = -EIO;
2139 goto error_open;
2140 }
2141 if (out->offload_callback)
2142 compress_nonblock(out->compr, out->non_blocking);
2143
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002144 if (adev->visualizer_start_output != NULL) {
2145 int capture_device_id =
2146 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2147 PCM_CAPTURE);
2148 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2149 adev->snd_card, capture_device_id);
2150 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002151 if (adev->offload_effects_start_output != NULL)
2152 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2153 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002154 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002155 ALOGE("%s: pcm stream not ready", __func__);
2156 goto error_open;
2157 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002158 ret = pcm_start(out->pcm);
2159 if (ret < 0) {
2160 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2161 goto error_open;
2162 }
2163 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002164 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002165 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002166
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002167 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2168 flags |= PCM_MMAP | PCM_NOIRQ;
2169 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002170 } else if (out->realtime) {
2171 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002172 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002173
2174 while (1) {
2175 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2176 flags, &out->config);
2177 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2178 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2179 if (out->pcm != NULL) {
2180 pcm_close(out->pcm);
2181 out->pcm = NULL;
2182 }
2183 if (pcm_open_retry_count-- == 0) {
2184 ret = -EIO;
2185 goto error_open;
2186 }
2187 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2188 continue;
2189 }
2190 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002192 ALOGV("%s: pcm_prepare", __func__);
2193 if (pcm_is_ready(out->pcm)) {
2194 ret = pcm_prepare(out->pcm);
2195 if (ret < 0) {
2196 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2197 pcm_close(out->pcm);
2198 out->pcm = NULL;
2199 goto error_open;
2200 }
2201 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002202 if (out->realtime) {
2203 ret = pcm_start(out->pcm);
2204 if (ret < 0) {
2205 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2206 pcm_close(out->pcm);
2207 out->pcm = NULL;
2208 goto error_open;
2209 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002210 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002211 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002212 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002213 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002214 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002215 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002216
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002217 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2218 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2219 audio_low_latency_hint_start();
2220 }
2221
vivek mehtae59cfb22017-06-16 15:57:11 -07002222 // consider a scenario where on pause lower layers are tear down.
2223 // so on resume, swap mixer control need to be sent only when
2224 // backend is active, hence rather than sending from enable device
2225 // sending it from start of streamtream
2226
2227 platform_set_swap_channels(adev, true);
2228
Eric Laurent994a6932013-07-17 11:51:42 -07002229 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002230 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002232 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002233 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002235error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002236 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237}
2238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239static int check_input_parameters(uint32_t sample_rate,
2240 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002241 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002243 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2244 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002245 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2246 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002247 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2248 return -EINVAL;
2249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250
Eric Laurent74b55762017-07-09 17:04:53 -07002251 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2252 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002253 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002254 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002255 return -EINVAL;
2256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257
2258 switch (sample_rate) {
2259 case 8000:
2260 case 11025:
2261 case 12000:
2262 case 16000:
2263 case 22050:
2264 case 24000:
2265 case 32000:
2266 case 44100:
2267 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002268 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 break;
2270 default:
vivek mehtadae44712015-07-27 14:13:18 -07002271 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 return -EINVAL;
2273 }
2274
2275 return 0;
2276}
2277
Kevin Rocarda325aa22018-04-03 09:15:52 -07002278/** Add a value in a list if not already present.
2279 * @return true if value was successfully inserted or already present,
2280 * false if the list is full and does not contain the value.
2281 */
2282static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2283 for (size_t i = 0; i < list_length; i++) {
2284 if (list[i] == value) return true; // value is already present
2285 if (list[i] == 0) { // no values in this slot
2286 list[i] = value;
2287 return true; // value inserted
2288 }
2289 }
2290 return false; // could not insert value
2291}
2292
2293/** Add channel_mask in supported_channel_masks if not already present.
2294 * @return true if channel_mask was successfully inserted or already present,
2295 * false if supported_channel_masks is full and does not contain channel_mask.
2296 */
2297static void register_channel_mask(audio_channel_mask_t channel_mask,
2298 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2299 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2300 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2301}
2302
2303/** Add format in supported_formats if not already present.
2304 * @return true if format was successfully inserted or already present,
2305 * false if supported_formats is full and does not contain format.
2306 */
2307static void register_format(audio_format_t format,
2308 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2309 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2310 "%s: stream can not declare supporting its format %x", __func__, format);
2311}
2312/** Add sample_rate in supported_sample_rates if not already present.
2313 * @return true if sample_rate was successfully inserted or already present,
2314 * false if supported_sample_rates is full and does not contain sample_rate.
2315 */
2316static void register_sample_rate(uint32_t sample_rate,
2317 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2318 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2319 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2320}
2321
vivek mehtaa68fea62017-06-08 19:04:02 -07002322static size_t get_stream_buffer_size(size_t duration_ms,
2323 uint32_t sample_rate,
2324 audio_format_t format,
2325 int channel_count,
2326 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002327{
2328 size_t size = 0;
2329
vivek mehtaa68fea62017-06-08 19:04:02 -07002330 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002331 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002332 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002333
2334 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335
Glenn Kasten4f993392014-05-14 07:30:48 -07002336 /* make sure the size is multiple of 32 bytes
2337 * At 48 kHz mono 16-bit PCM:
2338 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2339 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2340 */
2341 size += 0x1f;
2342 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002343
2344 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345}
2346
2347static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2348{
2349 struct stream_out *out = (struct stream_out *)stream;
2350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002351 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352}
2353
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002354static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355{
2356 return -ENOSYS;
2357}
2358
2359static size_t out_get_buffer_size(const struct audio_stream *stream)
2360{
2361 struct stream_out *out = (struct stream_out *)stream;
2362
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2364 return out->compr_config.fragment_size;
2365 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002366 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002367 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368}
2369
2370static uint32_t out_get_channels(const struct audio_stream *stream)
2371{
2372 struct stream_out *out = (struct stream_out *)stream;
2373
2374 return out->channel_mask;
2375}
2376
2377static audio_format_t out_get_format(const struct audio_stream *stream)
2378{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 struct stream_out *out = (struct stream_out *)stream;
2380
2381 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382}
2383
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002384static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385{
2386 return -ENOSYS;
2387}
2388
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002389/* must be called with out->lock locked */
2390static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391{
2392 struct stream_out *out = (struct stream_out *)stream;
2393 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002394 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002397 if (adev->adm_deregister_stream)
2398 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002399 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002400 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2402 if (out->pcm) {
2403 pcm_close(out->pcm);
2404 out->pcm = NULL;
2405 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002406 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002407 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002408 out->playback_started = false;
2409 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 } else {
2411 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002412 out->gapless_mdata.encoder_delay = 0;
2413 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 if (out->compr != NULL) {
2415 compress_close(out->compr);
2416 out->compr = NULL;
2417 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002418 }
Phil Burkbc991042017-02-24 08:06:44 -08002419 if (do_stop) {
2420 stop_output_stream(out);
2421 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002422 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002424 return 0;
2425}
2426
2427static int out_standby(struct audio_stream *stream)
2428{
2429 struct stream_out *out = (struct stream_out *)stream;
2430
2431 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2432 out->usecase, use_case_table[out->usecase]);
2433
2434 lock_output_stream(out);
2435 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002437 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438 return 0;
2439}
2440
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002441static int out_on_error(struct audio_stream *stream)
2442{
2443 struct stream_out *out = (struct stream_out *)stream;
2444 struct audio_device *adev = out->dev;
2445 bool do_standby = false;
2446
2447 lock_output_stream(out);
2448 if (!out->standby) {
2449 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2450 stop_compressed_output_l(out);
2451 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2452 } else
2453 do_standby = true;
2454 }
2455 pthread_mutex_unlock(&out->lock);
2456
2457 if (do_standby)
2458 return out_standby(&out->stream.common);
2459
2460 return 0;
2461}
2462
Andy Hung7401c7c2016-09-21 12:41:21 -07002463static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464{
Andy Hung7401c7c2016-09-21 12:41:21 -07002465 struct stream_out *out = (struct stream_out *)stream;
2466
2467 // We try to get the lock for consistency,
2468 // but it isn't necessary for these variables.
2469 // If we're not in standby, we may be blocked on a write.
2470 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2471 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2472 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2473
2474 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002475 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002476 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002477
2478 // dump error info
2479 (void)error_log_dump(
2480 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 return 0;
2483}
2484
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002485static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2486{
2487 int ret = 0;
2488 char value[32];
2489 struct compr_gapless_mdata tmp_mdata;
2490
2491 if (!out || !parms) {
2492 return -EINVAL;
2493 }
2494
2495 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2496 if (ret >= 0) {
2497 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2498 } else {
2499 return -EINVAL;
2500 }
2501
2502 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2503 if (ret >= 0) {
2504 tmp_mdata.encoder_padding = atoi(value);
2505 } else {
2506 return -EINVAL;
2507 }
2508
2509 out->gapless_mdata = tmp_mdata;
2510 out->send_new_metadata = 1;
2511 ALOGV("%s new encoder delay %u and padding %u", __func__,
2512 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2513
2514 return 0;
2515}
2516
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002517static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2518{
2519 return out == adev->primary_output || out == adev->voice_tx_output;
2520}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002521
Kevin Rocard1e02c882017-08-09 15:26:07 -07002522static int get_alive_usb_card(struct str_parms* parms) {
2523 int card;
2524 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2525 !audio_extn_usb_alive(card)) {
2526 return card;
2527 }
2528 return -ENODEV;
2529}
2530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2532{
2533 struct stream_out *out = (struct stream_out *)stream;
2534 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002535 struct audio_usecase *usecase;
2536 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 struct str_parms *parms;
2538 char value[32];
2539 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002540 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002541 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002542 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543
Eric Laurent2e140aa2016-06-30 17:14:46 -07002544 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002545 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 parms = str_parms_create_str(kvpairs);
2547 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2548 if (ret >= 0) {
2549 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002550
Eric Laurenta1478072015-09-21 17:21:52 -07002551 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002552
2553 // The usb driver needs to be closed after usb device disconnection
2554 // otherwise audio is no longer played on the new usb devices.
2555 // By forcing the stream in standby, the usb stack refcount drops to 0
2556 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002557 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002558 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002559 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2560 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2561 out_standby_l(&out->stream.common);
2562 }
2563 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002564 }
2565
Eric Laurent150dbfe2013-02-27 14:31:02 -08002566 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002568 /*
2569 * When HDMI cable is unplugged the music playback is paused and
2570 * the policy manager sends routing=0. But the audioflinger
2571 * continues to write data until standby time (3sec).
2572 * As the HDMI core is turned off, the write gets blocked.
2573 * Avoid this by routing audio to speaker until standby.
2574 */
2575 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2576 val == AUDIO_DEVICE_NONE) {
2577 val = AUDIO_DEVICE_OUT_SPEAKER;
2578 }
2579
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002580 /*
2581 * When A2DP is disconnected the
2582 * music playback is paused and the policy manager sends routing=0
2583 * But the audioflingercontinues to write data until standby time
2584 * (3sec). As BT is turned off, the write gets blocked.
2585 * Avoid this by routing audio to speaker until standby.
2586 */
2587 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2588 (val == AUDIO_DEVICE_NONE) &&
2589 !audio_extn_a2dp_is_ready()) {
2590 val = AUDIO_DEVICE_OUT_SPEAKER;
2591 }
2592
2593 /* To avoid a2dp to sco overlapping / BT device improper state
2594 * check with BT lib about a2dp streaming support before routing
2595 */
2596 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2597 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002598 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002599 //combo usecase just by pass a2dp
2600 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2601 bypass_a2dp = true;
2602 } else {
2603 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2604 /* update device to a2dp and don't route as BT returned error
2605 * However it is still possible a2dp routing called because
2606 * of current active device disconnection (like wired headset)
2607 */
2608 out->devices = val;
2609 pthread_mutex_unlock(&out->lock);
2610 pthread_mutex_unlock(&adev->lock);
2611 status = -ENOSYS;
2612 goto routing_fail;
2613 }
2614 }
2615 }
2616
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002617 audio_devices_t new_dev = val;
2618
2619 // Workaround: If routing to an non existing usb device, fail gracefully
2620 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002621 int card;
2622 if (audio_is_usb_out_device(new_dev) &&
2623 (card = get_alive_usb_card(parms)) >= 0) {
2624
2625 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002626 pthread_mutex_unlock(&adev->lock);
2627 pthread_mutex_unlock(&out->lock);
2628 status = -ENOSYS;
2629 goto routing_fail;
2630 }
2631
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 /*
2633 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002634 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635 * the select_devices(). But how do we undo this?
2636 *
2637 * For example, music playback is active on headset (deep-buffer usecase)
2638 * and if we go to ringtones and select a ringtone, low-latency usecase
2639 * will be started on headset+speaker. As we can't enable headset+speaker
2640 * and headset devices at the same time, select_devices() switches the music
2641 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2642 * So when the ringtone playback is completed, how do we undo the same?
2643 *
2644 * We are relying on the out_set_parameters() call on deep-buffer output,
2645 * once the ringtone playback is ended.
2646 * NOTE: We should not check if the current devices are same as new devices.
2647 * Because select_devices() must be called to switch back the music
2648 * playback to headset.
2649 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002650 if (new_dev != AUDIO_DEVICE_NONE) {
2651 bool same_dev = out->devices == new_dev;
2652 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002653
Eric Laurenta7657192014-10-09 21:09:33 -07002654 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002655 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002656 if (adev->mode == AUDIO_MODE_IN_CALL) {
2657 adev->current_call_output = out;
2658 ret = voice_start_call(adev);
2659 }
2660 } else {
2661 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002662 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002663 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002664 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002665
2666 if (!out->standby) {
2667 if (!same_dev) {
2668 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002669 // inform adm before actual routing to prevent glitches.
2670 if (adev->adm_on_routing_change) {
2671 adev->adm_on_routing_change(adev->adm_data,
2672 out->handle);
2673 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002674 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002675 if (!bypass_a2dp) {
2676 select_devices(adev, out->usecase);
2677 } else {
juyuchen9baad392018-06-05 19:02:10 +08002678 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2679 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2680 else
2681 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002682 select_devices(adev, out->usecase);
2683 out->devices = new_dev;
2684 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002685 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002686
2687 // on device switch force swap, lower functions will make sure
2688 // to check if swap is allowed or not.
2689
2690 if (!same_dev)
2691 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002692
2693 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2694 out->a2dp_compress_mute &&
2695 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2696 pthread_mutex_lock(&out->compr_mute_lock);
2697 out->a2dp_compress_mute = false;
2698 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2699 pthread_mutex_unlock(&out->compr_mute_lock);
2700 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002701 }
2702
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002703 }
2704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002706 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002707
2708 /*handles device and call state changes*/
2709 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002711 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002712
2713 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2714 parse_compress_metadata(out, parms);
2715 }
2716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002718 ALOGV("%s: exit: code(%d)", __func__, status);
2719 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002720}
2721
Haynes Mathew George569b7482017-05-08 14:44:27 -07002722static bool stream_get_parameter_channels(struct str_parms *query,
2723 struct str_parms *reply,
2724 audio_channel_mask_t *supported_channel_masks) {
2725 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002726 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002728 size_t i, j;
2729
2730 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2731 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732 value[0] = '\0';
2733 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002734 while (supported_channel_masks[i] != 0) {
2735 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2736 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 if (!first) {
2738 strcat(value, "|");
2739 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002740 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741 first = false;
2742 break;
2743 }
2744 }
2745 i++;
2746 }
2747 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002748 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002749 return ret >= 0;
2750}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002751
Haynes Mathew George569b7482017-05-08 14:44:27 -07002752static bool stream_get_parameter_formats(struct str_parms *query,
2753 struct str_parms *reply,
2754 audio_format_t *supported_formats) {
2755 int ret = -1;
2756 char value[256];
2757 int i;
2758
2759 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2760 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002761 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002762 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002763 case AUDIO_FORMAT_PCM_16_BIT:
2764 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2765 break;
2766 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2767 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2768 break;
2769 case AUDIO_FORMAT_PCM_32_BIT:
2770 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2771 break;
2772 default:
2773 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002774 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002775 break;
2776 }
2777 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002778 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002779 return ret >= 0;
2780}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002781
Haynes Mathew George569b7482017-05-08 14:44:27 -07002782static bool stream_get_parameter_rates(struct str_parms *query,
2783 struct str_parms *reply,
2784 uint32_t *supported_sample_rates) {
2785
2786 int i;
2787 char value[256];
2788 int ret = -1;
2789 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2790 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002791 value[0] = '\0';
2792 i=0;
2793 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002794 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002795 int avail = sizeof(value) - cursor;
2796 ret = snprintf(value + cursor, avail, "%s%d",
2797 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002798 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002799 if (ret < 0 || ret >= avail) {
2800 // if cursor is at the last element of the array
2801 // overwrite with \0 is duplicate work as
2802 // snprintf already put a \0 in place.
2803 // else
2804 // we had space to write the '|' at value[cursor]
2805 // (which will be overwritten) or no space to fill
2806 // the first element (=> cursor == 0)
2807 value[cursor] = '\0';
2808 break;
2809 }
2810 cursor += ret;
2811 ++i;
2812 }
2813 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2814 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002815 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002816 return ret >= 0;
2817}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002818
Haynes Mathew George569b7482017-05-08 14:44:27 -07002819static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2820{
2821 struct stream_out *out = (struct stream_out *)stream;
2822 struct str_parms *query = str_parms_create_str(keys);
2823 char *str;
2824 struct str_parms *reply = str_parms_create();
2825 bool replied = false;
2826 ALOGV("%s: enter: keys - %s", __func__, keys);
2827
2828 replied |= stream_get_parameter_channels(query, reply,
2829 &out->supported_channel_masks[0]);
2830 replied |= stream_get_parameter_formats(query, reply,
2831 &out->supported_formats[0]);
2832 replied |= stream_get_parameter_rates(query, reply,
2833 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002834 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 str = str_parms_to_str(reply);
2836 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002837 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839 str_parms_destroy(query);
2840 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002841 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 return str;
2843}
2844
2845static uint32_t out_get_latency(const struct audio_stream_out *stream)
2846{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002847 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002849 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002850
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002851 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2852 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002853 else if ((out->realtime) ||
2854 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002855 // since the buffer won't be filled up faster than realtime,
2856 // return a smaller number
2857 period_ms = (out->af_period_multiplier * out->config.period_size *
2858 1000) / (out->config.rate);
2859 hw_delay = platform_render_latency(out->usecase)/1000;
2860 return period_ms + hw_delay;
2861 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002862
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002863 latency = (out->config.period_count * out->config.period_size * 1000) /
2864 (out->config.rate);
2865
2866 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2867 latency += audio_extn_a2dp_get_encoder_latency();
2868
2869 return latency;
2870}
2871
2872static int set_compr_volume(struct audio_stream_out *stream, float left,
2873 float right)
2874{
2875 struct stream_out *out = (struct stream_out *)stream;
2876 int volume[2];
2877 char mixer_ctl_name[128];
2878 struct audio_device *adev = out->dev;
2879 struct mixer_ctl *ctl;
2880 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2881 PCM_PLAYBACK);
2882
2883 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2884 "Compress Playback %d Volume", pcm_device_id);
2885 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2886 if (!ctl) {
2887 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2888 __func__, mixer_ctl_name);
2889 return -EINVAL;
2890 }
2891 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2892 __func__, mixer_ctl_name, left, right);
2893 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2894 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2895 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2896
2897 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898}
2899
2900static int out_set_volume(struct audio_stream_out *stream, float left,
2901 float right)
2902{
Eric Laurenta9024de2013-04-04 09:19:12 -07002903 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002904 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002906 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002907 /* only take left channel into account: the API is for stereo anyway */
2908 out->muted = (left == 0.0f);
2909 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002910 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002911 pthread_mutex_lock(&out->compr_mute_lock);
2912 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2913 if (!out->a2dp_compress_mute)
2914 ret = set_compr_volume(stream, left, right);
2915 out->volume_l = left;
2916 out->volume_r = right;
2917 pthread_mutex_unlock(&out->compr_mute_lock);
2918 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002919 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002920 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2921 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2922 if (!out->standby) {
2923 // if in standby, cached volume will be sent after stream is opened
2924 audio_extn_utils_send_app_type_gain(out->dev,
2925 out->app_type_cfg.app_type,
2926 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002927 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002928 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002929 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 return -ENOSYS;
2932}
2933
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002934// note: this call is safe only if the stream_cb is
2935// removed first in close_output_stream (as is done now).
2936static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2937{
2938 if (!stream || !parms)
2939 return;
2940
2941 struct stream_out *out = (struct stream_out *)stream;
2942 struct audio_device *adev = out->dev;
2943
2944 card_status_t status;
2945 int card;
2946 if (parse_snd_card_status(parms, &card, &status) < 0)
2947 return;
2948
2949 pthread_mutex_lock(&adev->lock);
2950 bool valid_cb = (card == adev->snd_card);
2951 pthread_mutex_unlock(&adev->lock);
2952
2953 if (!valid_cb)
2954 return;
2955
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002956 lock_output_stream(out);
2957 if (out->card_status != status)
2958 out->card_status = status;
2959 pthread_mutex_unlock(&out->lock);
2960
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002961 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2962 use_case_table[out->usecase],
2963 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2964
2965 if (status == CARD_STATUS_OFFLINE)
2966 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002967
2968 return;
2969}
2970
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002971#ifdef NO_AUDIO_OUT
2972static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002973 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002974{
2975 struct stream_out *out = (struct stream_out *)stream;
2976
2977 /* No Output device supported other than BT for playback.
2978 * Sleep for the amount of buffer duration
2979 */
Eric Laurenta1478072015-09-21 17:21:52 -07002980 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002981 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2982 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002983 out_get_sample_rate(&out->stream.common));
2984 pthread_mutex_unlock(&out->lock);
2985 return bytes;
2986}
2987#endif
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2990 size_t bytes)
2991{
2992 struct stream_out *out = (struct stream_out *)stream;
2993 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002994 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002995 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996
Eric Laurenta1478072015-09-21 17:21:52 -07002997 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002998 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002999 const size_t frame_size = audio_stream_out_frame_size(stream);
3000 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003001
Eric Laurent0e46adf2016-12-16 12:49:24 -08003002 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3003 error_code = ERROR_CODE_WRITE;
3004 goto exit;
3005 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003006
3007 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3008 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003009 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003010 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3011 ret = -EIO;
3012 goto exit;
3013 }
3014 }
3015 }
3016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003018 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003019 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003021
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003022 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003024 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003025 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 goto exit;
3027 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003028
vivek mehta40125092017-08-21 18:48:51 -07003029 // after standby always force set last known cal step
3030 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3031 ALOGD("%s: retry previous failed cal level set", __func__);
3032 send_gain_dep_calibration_l();
3033 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003036 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003037 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003038 if (out->send_new_metadata) {
3039 ALOGVV("send new gapless metadata");
3040 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3041 out->send_new_metadata = 0;
3042 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003043 unsigned int avail;
3044 struct timespec tstamp;
3045 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3046 /* Do not limit write size if the available frames count is unknown */
3047 if (ret != 0) {
3048 avail = bytes;
3049 }
3050 if (avail == 0) {
3051 ret = 0;
3052 } else {
3053 if (avail > bytes) {
3054 avail = bytes;
3055 }
3056 ret = compress_write(out->compr, buffer, avail);
3057 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3058 __func__, avail, ret);
3059 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003060
Eric Laurent6e895242013-09-05 16:10:57 -07003061 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3063 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003064 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065 compress_start(out->compr);
3066 out->playback_started = 1;
3067 out->offload_state = OFFLOAD_STATE_PLAYING;
3068 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003069 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003070 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003071 } else {
3072 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003073 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003075 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003076 return ret;
3077 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003078 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003079 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003080 size_t bytes_to_write = bytes;
3081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003082 if (out->muted)
3083 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003084 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003085 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003086 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3087 int16_t *src = (int16_t *)buffer;
3088 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003089
Eric Laurentad2dde92017-09-20 18:27:31 -07003090 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3091 out->format != AUDIO_FORMAT_PCM_16_BIT,
3092 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003093
Eric Laurentad2dde92017-09-20 18:27:31 -07003094 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3095 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3096 }
3097 bytes_to_write /= 2;
3098 }
3099 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3100
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003101 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003102 request_out_focus(out, ns);
3103
3104 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3105 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003106 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003107 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003108 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003109
Haynes Mathew George03c40102016-01-29 17:57:48 -08003110 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003111 } else {
3112 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 }
3115
3116exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003117 // For PCM we always consume the buffer and return #bytes regardless of ret.
3118 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003119 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003120 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003121 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003122
Andy Hung7401c7c2016-09-21 12:41:21 -07003123 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003124 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003125 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3126 ALOGE_IF(out->pcm != NULL,
3127 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003128 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003129 // usleep not guaranteed for values over 1 second but we don't limit here.
3130 }
3131 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 pthread_mutex_unlock(&out->lock);
3134
3135 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003136 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003137 if (sleeptime_us != 0)
3138 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 }
3140 return bytes;
3141}
3142
3143static int out_get_render_position(const struct audio_stream_out *stream,
3144 uint32_t *dsp_frames)
3145{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 struct stream_out *out = (struct stream_out *)stream;
3147 *dsp_frames = 0;
3148 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003149 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003151 unsigned long frames = 0;
3152 // TODO: check return value
3153 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3154 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003155 ALOGVV("%s rendered frames %d sample_rate %d",
3156 __func__, *dsp_frames, out->sample_rate);
3157 }
3158 pthread_mutex_unlock(&out->lock);
3159 return 0;
3160 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003161 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162}
3163
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003164static int out_add_audio_effect(const struct audio_stream *stream __unused,
3165 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166{
3167 return 0;
3168}
3169
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003170static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3171 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172{
3173 return 0;
3174}
3175
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003176static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3177 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003178{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003179 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180}
3181
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003182static int out_get_presentation_position(const struct audio_stream_out *stream,
3183 uint64_t *frames, struct timespec *timestamp)
3184{
3185 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003186 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003187 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003188
Eric Laurenta1478072015-09-21 17:21:52 -07003189 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003190
Eric Laurent949a0892013-09-20 09:20:13 -07003191 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3192 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003193 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003194 compress_get_tstamp(out->compr, &dsp_frames,
3195 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003196 // Adjustment accounts for A2DP encoder latency with offload usecases
3197 // Note: Encoder latency is returned in ms.
3198 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3199 unsigned long offset =
3200 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3201 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3202 }
Eric Laurent949a0892013-09-20 09:20:13 -07003203 ALOGVV("%s rendered frames %ld sample_rate %d",
3204 __func__, dsp_frames, out->sample_rate);
3205 *frames = dsp_frames;
3206 ret = 0;
3207 /* this is the best we can do */
3208 clock_gettime(CLOCK_MONOTONIC, timestamp);
3209 }
3210 } else {
3211 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003212 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003213 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3214 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003215 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003216 // This adjustment accounts for buffering after app processor.
3217 // It is based on estimated DSP latency per use case, rather than exact.
3218 signed_frames -=
3219 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3220
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003221 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3222 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3223 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3224 signed_frames -=
3225 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3226 }
3227
Eric Laurent949a0892013-09-20 09:20:13 -07003228 // It would be unusual for this value to be negative, but check just in case ...
3229 if (signed_frames >= 0) {
3230 *frames = signed_frames;
3231 ret = 0;
3232 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003233 }
3234 }
3235 }
3236
3237 pthread_mutex_unlock(&out->lock);
3238
3239 return ret;
3240}
3241
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003242static int out_set_callback(struct audio_stream_out *stream,
3243 stream_callback_t callback, void *cookie)
3244{
3245 struct stream_out *out = (struct stream_out *)stream;
3246
3247 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003248 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003249 out->offload_callback = callback;
3250 out->offload_cookie = cookie;
3251 pthread_mutex_unlock(&out->lock);
3252 return 0;
3253}
3254
3255static int out_pause(struct audio_stream_out* stream)
3256{
3257 struct stream_out *out = (struct stream_out *)stream;
3258 int status = -ENOSYS;
3259 ALOGV("%s", __func__);
3260 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003261 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003262 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3263 status = compress_pause(out->compr);
3264 out->offload_state = OFFLOAD_STATE_PAUSED;
3265 }
3266 pthread_mutex_unlock(&out->lock);
3267 }
3268 return status;
3269}
3270
3271static int out_resume(struct audio_stream_out* stream)
3272{
3273 struct stream_out *out = (struct stream_out *)stream;
3274 int status = -ENOSYS;
3275 ALOGV("%s", __func__);
3276 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3277 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003278 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3280 status = compress_resume(out->compr);
3281 out->offload_state = OFFLOAD_STATE_PLAYING;
3282 }
3283 pthread_mutex_unlock(&out->lock);
3284 }
3285 return status;
3286}
3287
3288static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3289{
3290 struct stream_out *out = (struct stream_out *)stream;
3291 int status = -ENOSYS;
3292 ALOGV("%s", __func__);
3293 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003294 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003295 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3296 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3297 else
3298 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3299 pthread_mutex_unlock(&out->lock);
3300 }
3301 return status;
3302}
3303
3304static int out_flush(struct audio_stream_out* stream)
3305{
3306 struct stream_out *out = (struct stream_out *)stream;
3307 ALOGV("%s", __func__);
3308 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003309 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310 stop_compressed_output_l(out);
3311 pthread_mutex_unlock(&out->lock);
3312 return 0;
3313 }
3314 return -ENOSYS;
3315}
3316
Eric Laurent0e46adf2016-12-16 12:49:24 -08003317static int out_stop(const struct audio_stream_out* stream)
3318{
3319 struct stream_out *out = (struct stream_out *)stream;
3320 struct audio_device *adev = out->dev;
3321 int ret = -ENOSYS;
3322
3323 ALOGV("%s", __func__);
3324 pthread_mutex_lock(&adev->lock);
3325 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3326 out->playback_started && out->pcm != NULL) {
3327 pcm_stop(out->pcm);
3328 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003329 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003330 }
3331 pthread_mutex_unlock(&adev->lock);
3332 return ret;
3333}
3334
3335static int out_start(const struct audio_stream_out* stream)
3336{
3337 struct stream_out *out = (struct stream_out *)stream;
3338 struct audio_device *adev = out->dev;
3339 int ret = -ENOSYS;
3340
3341 ALOGV("%s", __func__);
3342 pthread_mutex_lock(&adev->lock);
3343 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3344 !out->playback_started && out->pcm != NULL) {
3345 ret = start_output_stream(out);
3346 if (ret == 0) {
3347 out->playback_started = true;
3348 }
3349 }
3350 pthread_mutex_unlock(&adev->lock);
3351 return ret;
3352}
3353
Phil Burkbc991042017-02-24 08:06:44 -08003354/*
3355 * Modify config->period_count based on min_size_frames
3356 */
3357static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3358{
3359 int periodCountRequested = (min_size_frames + config->period_size - 1)
3360 / config->period_size;
3361 int periodCount = MMAP_PERIOD_COUNT_MIN;
3362
3363 ALOGV("%s original config.period_size = %d config.period_count = %d",
3364 __func__, config->period_size, config->period_count);
3365
3366 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3367 periodCount *= 2;
3368 }
3369 config->period_count = periodCount;
3370
3371 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3372}
3373
Eric Laurent0e46adf2016-12-16 12:49:24 -08003374static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3375 int32_t min_size_frames,
3376 struct audio_mmap_buffer_info *info)
3377{
3378 struct stream_out *out = (struct stream_out *)stream;
3379 struct audio_device *adev = out->dev;
3380 int ret = 0;
3381 unsigned int offset1;
3382 unsigned int frames1;
3383 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003384 uint32_t mmap_size;
3385 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003386
3387 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003388 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003389 pthread_mutex_lock(&adev->lock);
3390
3391 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003392 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003393 ret = -EINVAL;
3394 goto exit;
3395 }
3396 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003397 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003398 ret = -ENOSYS;
3399 goto exit;
3400 }
3401 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3402 if (out->pcm_device_id < 0) {
3403 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3404 __func__, out->pcm_device_id, out->usecase);
3405 ret = -EINVAL;
3406 goto exit;
3407 }
Phil Burkbc991042017-02-24 08:06:44 -08003408
3409 adjust_mmap_period_count(&out->config, min_size_frames);
3410
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3412 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3413 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3414 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3415 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3416 step = "open";
3417 ret = -ENODEV;
3418 goto exit;
3419 }
3420 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3421 if (ret < 0) {
3422 step = "begin";
3423 goto exit;
3424 }
3425 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003426 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003427 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003428 ret = platform_get_mmap_data_fd(adev->platform,
3429 out->pcm_device_id, 0 /*playback*/,
3430 &info->shared_memory_fd,
3431 &mmap_size);
3432 if (ret < 0) {
3433 // Fall back to non exclusive mode
3434 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3435 } else {
3436 if (mmap_size < buffer_size) {
3437 step = "mmap";
3438 goto exit;
3439 }
3440 // FIXME: indicate exclusive mode support by returning a negative buffer size
3441 info->buffer_size_frames *= -1;
3442 }
3443 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444
3445 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3446 if (ret < 0) {
3447 step = "commit";
3448 goto exit;
3449 }
Phil Burkbc991042017-02-24 08:06:44 -08003450
3451 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003452 ret = 0;
3453
3454 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3455 __func__, info->shared_memory_address, info->buffer_size_frames);
3456
3457exit:
3458 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003459 if (out->pcm == NULL) {
3460 ALOGE("%s: %s - %d", __func__, step, ret);
3461 } else {
3462 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003463 pcm_close(out->pcm);
3464 out->pcm = NULL;
3465 }
3466 }
3467 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003468 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003469 return ret;
3470}
3471
3472static int out_get_mmap_position(const struct audio_stream_out *stream,
3473 struct audio_mmap_position *position)
3474{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003475 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003476 struct stream_out *out = (struct stream_out *)stream;
3477 ALOGVV("%s", __func__);
3478 if (position == NULL) {
3479 return -EINVAL;
3480 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003481 lock_output_stream(out);
3482 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3483 out->pcm == NULL) {
3484 ret = -ENOSYS;
3485 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003486 }
3487
3488 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003489 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003490 if (ret < 0) {
3491 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003492 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003493 }
Andy Hungfc044e12017-03-20 09:24:22 -07003494 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003495exit:
3496 pthread_mutex_unlock(&out->lock);
3497 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003498}
3499
3500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501/** audio_stream_in implementation **/
3502static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3503{
3504 struct stream_in *in = (struct stream_in *)stream;
3505
3506 return in->config.rate;
3507}
3508
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003509static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510{
3511 return -ENOSYS;
3512}
3513
3514static size_t in_get_buffer_size(const struct audio_stream *stream)
3515{
3516 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003517 return in->config.period_size * in->af_period_multiplier *
3518 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519}
3520
3521static uint32_t in_get_channels(const struct audio_stream *stream)
3522{
3523 struct stream_in *in = (struct stream_in *)stream;
3524
3525 return in->channel_mask;
3526}
3527
vivek mehta4ed66e62016-04-15 23:33:34 -07003528static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529{
vivek mehta4ed66e62016-04-15 23:33:34 -07003530 struct stream_in *in = (struct stream_in *)stream;
3531 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532}
3533
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003534static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535{
3536 return -ENOSYS;
3537}
3538
3539static int in_standby(struct audio_stream *stream)
3540{
3541 struct stream_in *in = (struct stream_in *)stream;
3542 struct audio_device *adev = in->dev;
3543 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003544 bool do_stop = true;
3545
Eric Laurent994a6932013-07-17 11:51:42 -07003546 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003547
3548 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003549
3550 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003551 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003552 audio_extn_sound_trigger_stop_lab(in);
3553 in->standby = true;
3554 }
3555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003557 if (adev->adm_deregister_stream)
3558 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3559
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003560 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003562 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003563 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003564 in->capture_started = false;
3565 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003566 if (in->pcm) {
3567 pcm_close(in->pcm);
3568 in->pcm = NULL;
3569 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003570 adev->enable_voicerx = false;
3571 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003572 if (do_stop) {
3573 status = stop_input_stream(in);
3574 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003575 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576 }
3577 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003578 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 return status;
3580}
3581
Andy Hungd13f0d32017-06-12 13:58:37 -07003582static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003583{
Andy Hungd13f0d32017-06-12 13:58:37 -07003584 struct stream_in *in = (struct stream_in *)stream;
3585
3586 // We try to get the lock for consistency,
3587 // but it isn't necessary for these variables.
3588 // If we're not in standby, we may be blocked on a read.
3589 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3590 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3591 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3592 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3593
3594 if (locked) {
3595 pthread_mutex_unlock(&in->lock);
3596 }
3597
3598 // dump error info
3599 (void)error_log_dump(
3600 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003601 return 0;
3602}
3603
3604static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3605{
3606 struct stream_in *in = (struct stream_in *)stream;
3607 struct audio_device *adev = in->dev;
3608 struct str_parms *parms;
3609 char *str;
3610 char value[32];
3611 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003612 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Eric Laurent994a6932013-07-17 11:51:42 -07003614 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003615 parms = str_parms_create_str(kvpairs);
3616
3617 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3618
Eric Laurenta1478072015-09-21 17:21:52 -07003619 lock_input_stream(in);
3620
Eric Laurent150dbfe2013-02-27 14:31:02 -08003621 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 if (ret >= 0) {
3623 val = atoi(value);
3624 /* no audio source uses val == 0 */
3625 if ((in->source != val) && (val != 0)) {
3626 in->source = val;
3627 }
3628 }
3629
3630 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632 if (ret >= 0) {
3633 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003634 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003635
3636 // Workaround: If routing to an non existing usb device, fail gracefully
3637 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003638 int card;
3639 if (audio_is_usb_in_device(val) &&
3640 (card = get_alive_usb_card(parms)) >= 0) {
3641
3642 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003643 status = -ENOSYS;
3644 } else {
3645
3646 in->device = val;
3647 /* If recording is in progress, change the tx device to new device */
3648 if (!in->standby) {
3649 ALOGV("update input routing change");
3650 // inform adm before actual routing to prevent glitches.
3651 if (adev->adm_on_routing_change) {
3652 adev->adm_on_routing_change(adev->adm_data,
3653 in->capture_handle);
3654 }
3655 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003656 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 }
3659 }
3660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003662 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003663
3664 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003665 ALOGV("%s: exit: status(%d)", __func__, status);
3666 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667}
3668
Haynes Mathew George569b7482017-05-08 14:44:27 -07003669static char* in_get_parameters(const struct audio_stream *stream,
3670 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003672 struct stream_in *in = (struct stream_in *)stream;
3673 struct str_parms *query = str_parms_create_str(keys);
3674 char *str;
3675 struct str_parms *reply = str_parms_create();
3676 bool replied = false;
3677
3678 ALOGV("%s: enter: keys - %s", __func__, keys);
3679 replied |= stream_get_parameter_channels(query, reply,
3680 &in->supported_channel_masks[0]);
3681 replied |= stream_get_parameter_formats(query, reply,
3682 &in->supported_formats[0]);
3683 replied |= stream_get_parameter_rates(query, reply,
3684 &in->supported_sample_rates[0]);
3685 if (replied) {
3686 str = str_parms_to_str(reply);
3687 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003688 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003689 }
3690 str_parms_destroy(query);
3691 str_parms_destroy(reply);
3692 ALOGV("%s: exit: returns - %s", __func__, str);
3693 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694}
3695
Eric Laurent51f3c662018-04-10 18:21:34 -07003696static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697{
Eric Laurent51f3c662018-04-10 18:21:34 -07003698 struct stream_in *in = (struct stream_in *)stream;
3699 char mixer_ctl_name[128];
3700 struct mixer_ctl *ctl;
3701 int ctl_value;
3702
3703 ALOGV("%s: gain %f", __func__, gain);
3704
3705 if (stream == NULL)
3706 return -EINVAL;
3707
3708 /* in_set_gain() only used to silence MMAP capture for now */
3709 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3710 return -ENOSYS;
3711
3712 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3713
3714 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3715 if (!ctl) {
3716 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3717 __func__, mixer_ctl_name);
3718 return -ENOSYS;
3719 }
3720
3721 if (gain < RECORD_GAIN_MIN)
3722 gain = RECORD_GAIN_MIN;
3723 else if (gain > RECORD_GAIN_MAX)
3724 gain = RECORD_GAIN_MAX;
3725 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3726
3727 mixer_ctl_set_value(ctl, 0, ctl_value);
3728 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729}
3730
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003731static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3732{
3733 if (!stream || !parms)
3734 return;
3735
3736 struct stream_in *in = (struct stream_in *)stream;
3737 struct audio_device *adev = in->dev;
3738
3739 card_status_t status;
3740 int card;
3741 if (parse_snd_card_status(parms, &card, &status) < 0)
3742 return;
3743
3744 pthread_mutex_lock(&adev->lock);
3745 bool valid_cb = (card == adev->snd_card);
3746 pthread_mutex_unlock(&adev->lock);
3747
3748 if (!valid_cb)
3749 return;
3750
3751 lock_input_stream(in);
3752 if (in->card_status != status)
3753 in->card_status = status;
3754 pthread_mutex_unlock(&in->lock);
3755
3756 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3757 use_case_table[in->usecase],
3758 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3759
3760 // a better solution would be to report error back to AF and let
3761 // it put the stream to standby
3762 if (status == CARD_STATUS_OFFLINE)
3763 in_standby(&in->stream.common);
3764
3765 return;
3766}
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3769 size_t bytes)
3770{
3771 struct stream_in *in = (struct stream_in *)stream;
3772 struct audio_device *adev = in->dev;
3773 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003774 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003775 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776
Eric Laurenta1478072015-09-21 17:21:52 -07003777 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003778 const size_t frame_size = audio_stream_in_frame_size(stream);
3779 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003780
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003781 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003782 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003783 /* Read from sound trigger HAL */
3784 audio_extn_sound_trigger_read(in, buffer, bytes);
3785 pthread_mutex_unlock(&in->lock);
3786 return bytes;
3787 }
3788
Eric Laurent0e46adf2016-12-16 12:49:24 -08003789 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3790 ret = -ENOSYS;
3791 goto exit;
3792 }
3793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003795 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003797 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 goto exit;
3800 }
3801 in->standby = 0;
3802 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803
Andy Hungd13f0d32017-06-12 13:58:37 -07003804 // errors that occur here are read errors.
3805 error_code = ERROR_CODE_READ;
3806
Haynes Mathew George03c40102016-01-29 17:57:48 -08003807 //what's the duration requested by the client?
3808 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3809 in->config.rate;
3810 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003811
Haynes Mathew George03c40102016-01-29 17:57:48 -08003812 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003813 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003814 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003815 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003816 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003817 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003818 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003819 if (ret < 0) {
3820 ALOGE("Failed to read w/err %s", strerror(errno));
3821 ret = -errno;
3822 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003823 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3824 if (bytes % 4 == 0) {
3825 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3826 int_buf_stream = buffer;
3827 for (size_t itt=0; itt < bytes/4 ; itt++) {
3828 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003829 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003830 } else {
3831 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3832 ret = -EINVAL;
3833 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003834 }
3835 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003836 }
3837
Haynes Mathew George03c40102016-01-29 17:57:48 -08003838 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 /*
3841 * Instead of writing zeroes here, we could trust the hardware
3842 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003843 * 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 -08003844 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003845 if (ret == 0 && adev->mic_muted &&
3846 !voice_is_in_call_rec_stream(in) &&
3847 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003849 in->frames_muted += frames;
3850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851
3852exit:
3853 pthread_mutex_unlock(&in->lock);
3854
3855 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003856 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 in_standby(&in->stream.common);
3858 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003859 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003860 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003861 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003862 }
3863 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003864 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 }
3866 return bytes;
3867}
3868
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003869static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870{
3871 return 0;
3872}
3873
Andy Hung6ebe5962016-01-15 17:46:57 -08003874static int in_get_capture_position(const struct audio_stream_in *stream,
3875 int64_t *frames, int64_t *time)
3876{
3877 if (stream == NULL || frames == NULL || time == NULL) {
3878 return -EINVAL;
3879 }
3880 struct stream_in *in = (struct stream_in *)stream;
3881 int ret = -ENOSYS;
3882
3883 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003884 // note: ST sessions do not close the alsa pcm driver synchronously
3885 // on standby. Therefore, we may return an error even though the
3886 // pcm stream is still opened.
3887 if (in->standby) {
3888 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3889 "%s stream in standby but pcm not NULL for non ST session", __func__);
3890 goto exit;
3891 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003892 if (in->pcm) {
3893 struct timespec timestamp;
3894 unsigned int avail;
3895 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3896 *frames = in->frames_read + avail;
3897 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3898 ret = 0;
3899 }
3900 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003901exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003902 pthread_mutex_unlock(&in->lock);
3903 return ret;
3904}
3905
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003906static int add_remove_audio_effect(const struct audio_stream *stream,
3907 effect_handle_t effect,
3908 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003910 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003911 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003912 int status = 0;
3913 effect_descriptor_t desc;
3914
3915 status = (*effect)->get_descriptor(effect, &desc);
3916 if (status != 0)
3917 return status;
3918
Eric Laurenta1478072015-09-21 17:21:52 -07003919 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003920 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003921 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003922 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003923 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003924 in->enable_aec != enable &&
3925 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3926 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003927 if (!enable)
3928 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003929 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3930 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3931 adev->enable_voicerx = enable;
3932 struct audio_usecase *usecase;
3933 struct listnode *node;
3934 list_for_each(node, &adev->usecase_list) {
3935 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003936 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003937 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003938 }
3939 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003940 if (!in->standby)
3941 select_devices(in->dev, in->usecase);
3942 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003943 if (in->enable_ns != enable &&
3944 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3945 in->enable_ns = enable;
3946 if (!in->standby)
3947 select_devices(in->dev, in->usecase);
3948 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003949 pthread_mutex_unlock(&in->dev->lock);
3950 pthread_mutex_unlock(&in->lock);
3951
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 return 0;
3953}
3954
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003955static int in_add_audio_effect(const struct audio_stream *stream,
3956 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957{
Eric Laurent994a6932013-07-17 11:51:42 -07003958 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003959 return add_remove_audio_effect(stream, effect, true);
3960}
3961
3962static int in_remove_audio_effect(const struct audio_stream *stream,
3963 effect_handle_t effect)
3964{
Eric Laurent994a6932013-07-17 11:51:42 -07003965 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003966 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967}
3968
Eric Laurent0e46adf2016-12-16 12:49:24 -08003969static int in_stop(const struct audio_stream_in* stream)
3970{
3971 struct stream_in *in = (struct stream_in *)stream;
3972 struct audio_device *adev = in->dev;
3973
3974 int ret = -ENOSYS;
3975 ALOGV("%s", __func__);
3976 pthread_mutex_lock(&adev->lock);
3977 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3978 in->capture_started && in->pcm != NULL) {
3979 pcm_stop(in->pcm);
3980 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003981 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003982 }
3983 pthread_mutex_unlock(&adev->lock);
3984 return ret;
3985}
3986
3987static int in_start(const struct audio_stream_in* stream)
3988{
3989 struct stream_in *in = (struct stream_in *)stream;
3990 struct audio_device *adev = in->dev;
3991 int ret = -ENOSYS;
3992
3993 ALOGV("%s in %p", __func__, in);
3994 pthread_mutex_lock(&adev->lock);
3995 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3996 !in->capture_started && in->pcm != NULL) {
3997 if (!in->capture_started) {
3998 ret = start_input_stream(in);
3999 if (ret == 0) {
4000 in->capture_started = true;
4001 }
4002 }
4003 }
4004 pthread_mutex_unlock(&adev->lock);
4005 return ret;
4006}
4007
4008static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4009 int32_t min_size_frames,
4010 struct audio_mmap_buffer_info *info)
4011{
4012 struct stream_in *in = (struct stream_in *)stream;
4013 struct audio_device *adev = in->dev;
4014 int ret = 0;
4015 unsigned int offset1;
4016 unsigned int frames1;
4017 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004018 uint32_t mmap_size;
4019 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004020
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004021 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004022 pthread_mutex_lock(&adev->lock);
4023 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004024
Eric Laurent0e46adf2016-12-16 12:49:24 -08004025 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004026 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004027 ret = -EINVAL;
4028 goto exit;
4029 }
4030 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004031 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004032 ALOGV("%s in %p", __func__, in);
4033 ret = -ENOSYS;
4034 goto exit;
4035 }
4036 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4037 if (in->pcm_device_id < 0) {
4038 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4039 __func__, in->pcm_device_id, in->usecase);
4040 ret = -EINVAL;
4041 goto exit;
4042 }
Phil Burkbc991042017-02-24 08:06:44 -08004043
4044 adjust_mmap_period_count(&in->config, min_size_frames);
4045
Eric Laurent0e46adf2016-12-16 12:49:24 -08004046 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4047 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4048 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4049 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4050 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4051 step = "open";
4052 ret = -ENODEV;
4053 goto exit;
4054 }
4055
4056 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4057 if (ret < 0) {
4058 step = "begin";
4059 goto exit;
4060 }
4061 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004062 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004063 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004064 ret = platform_get_mmap_data_fd(adev->platform,
4065 in->pcm_device_id, 1 /*capture*/,
4066 &info->shared_memory_fd,
4067 &mmap_size);
4068 if (ret < 0) {
4069 // Fall back to non exclusive mode
4070 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4071 } else {
4072 if (mmap_size < buffer_size) {
4073 step = "mmap";
4074 goto exit;
4075 }
4076 // FIXME: indicate exclusive mode support by returning a negative buffer size
4077 info->buffer_size_frames *= -1;
4078 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004079
Haynes Mathew George96483a22017-03-28 14:52:47 -07004080 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004081
4082 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4083 if (ret < 0) {
4084 step = "commit";
4085 goto exit;
4086 }
4087
Phil Burkbc991042017-02-24 08:06:44 -08004088 in->standby = false;
4089 ret = 0;
4090
Eric Laurent0e46adf2016-12-16 12:49:24 -08004091 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4092 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004093
4094exit:
4095 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004096 if (in->pcm == NULL) {
4097 ALOGE("%s: %s - %d", __func__, step, ret);
4098 } else {
4099 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004100 pcm_close(in->pcm);
4101 in->pcm = NULL;
4102 }
4103 }
4104 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004105 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004106 return ret;
4107}
4108
4109static int in_get_mmap_position(const struct audio_stream_in *stream,
4110 struct audio_mmap_position *position)
4111{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004112 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004113 struct stream_in *in = (struct stream_in *)stream;
4114 ALOGVV("%s", __func__);
4115 if (position == NULL) {
4116 return -EINVAL;
4117 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004118 lock_input_stream(in);
4119 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4120 in->pcm == NULL) {
4121 ret = -ENOSYS;
4122 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004123 }
4124 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004125 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004126 if (ret < 0) {
4127 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004128 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004129 }
Andy Hungfc044e12017-03-20 09:24:22 -07004130 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004131exit:
4132 pthread_mutex_unlock(&in->lock);
4133 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004134}
4135
jiabin8962a4d2018-03-19 18:21:24 -07004136static int in_get_active_microphones(const struct audio_stream_in *stream,
4137 struct audio_microphone_characteristic_t *mic_array,
4138 size_t *mic_count) {
4139 struct stream_in *in = (struct stream_in *)stream;
4140 struct audio_device *adev = in->dev;
4141 ALOGVV("%s", __func__);
4142
4143 lock_input_stream(in);
4144 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004145 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004146 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004147 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004148 pthread_mutex_unlock(&adev->lock);
4149 pthread_mutex_unlock(&in->lock);
4150
4151 return ret;
4152}
4153
4154static int adev_get_microphones(const struct audio_hw_device *dev,
4155 struct audio_microphone_characteristic_t *mic_array,
4156 size_t *mic_count) {
4157 struct audio_device *adev = (struct audio_device *)dev;
4158 ALOGVV("%s", __func__);
4159
4160 pthread_mutex_lock(&adev->lock);
4161 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4162 pthread_mutex_unlock(&adev->lock);
4163
4164 return ret;
4165}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167static int adev_open_output_stream(struct audio_hw_device *dev,
4168 audio_io_handle_t handle,
4169 audio_devices_t devices,
4170 audio_output_flags_t flags,
4171 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004172 struct audio_stream_out **stream_out,
4173 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174{
4175 struct audio_device *adev = (struct audio_device *)dev;
4176 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004177 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004178 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4179 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4180 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181
Andy Hungd9653bd2017-08-01 19:31:39 -07004182 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4183 return -ENOSYS;
4184 }
4185
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004186 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4187 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 *stream_out = NULL;
4189 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4190
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004191 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 if (devices == AUDIO_DEVICE_NONE)
4194 devices = AUDIO_DEVICE_OUT_SPEAKER;
4195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 out->flags = flags;
4197 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004198 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004199 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004200 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201
4202 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004203 if ((is_hdmi || is_usb_dev) &&
4204 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4205 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4206 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004207 audio_format_t req_format = config->format;
4208 audio_channel_mask_t req_channel_mask = config->channel_mask;
4209 uint32_t req_sample_rate = config->sample_rate;
4210
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004211 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004212 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004213 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004214 if (config->sample_rate == 0)
4215 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004216 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004217 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4218 if (config->format == AUDIO_FORMAT_DEFAULT)
4219 config->format = AUDIO_FORMAT_PCM_16_BIT;
4220 } else if (is_usb_dev) {
4221 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4222 &config->format,
4223 &out->supported_formats[0],
4224 MAX_SUPPORTED_FORMATS,
4225 &config->channel_mask,
4226 &out->supported_channel_masks[0],
4227 MAX_SUPPORTED_CHANNEL_MASKS,
4228 &config->sample_rate,
4229 &out->supported_sample_rates[0],
4230 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004231 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004232 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004233 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004234 if (ret != 0) {
4235 // For MMAP NO IRQ, allow conversions in ADSP
4236 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4237 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004238
Eric Laurentab805ee2018-03-30 12:20:38 -07004239 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4240 config->sample_rate = req_sample_rate;
4241 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4242 config->channel_mask = req_channel_mask;
4243 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4244 config->format = req_format;
4245 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004246
Haynes Mathew George569b7482017-05-08 14:44:27 -07004247 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004248 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004249 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004250 if (is_hdmi) {
4251 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4252 out->config = pcm_config_hdmi_multi;
4253 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4254 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4255 out->config = pcm_config_mmap_playback;
4256 out->stream.start = out_start;
4257 out->stream.stop = out_stop;
4258 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4259 out->stream.get_mmap_position = out_get_mmap_position;
4260 } else {
4261 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4262 out->config = pcm_config_hifi;
4263 }
4264
4265 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004266 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004267 if (is_hdmi) {
4268 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4269 audio_bytes_per_sample(out->format));
4270 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004271 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004272 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004273 pthread_mutex_lock(&adev->lock);
4274 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4275 pthread_mutex_unlock(&adev->lock);
4276
4277 // reject offload during card offline to allow
4278 // fallback to s/w paths
4279 if (offline) {
4280 ret = -ENODEV;
4281 goto error_open;
4282 }
4283
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004284 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4285 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4286 ALOGE("%s: Unsupported Offload information", __func__);
4287 ret = -EINVAL;
4288 goto error_open;
4289 }
4290 if (!is_supported_format(config->offload_info.format)) {
4291 ALOGE("%s: Unsupported audio format", __func__);
4292 ret = -EINVAL;
4293 goto error_open;
4294 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004295 out->sample_rate = config->offload_info.sample_rate;
4296 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4297 out->channel_mask = config->offload_info.channel_mask;
4298 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4299 out->channel_mask = config->channel_mask;
4300 else
4301 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4302
4303 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004304
4305 out->compr_config.codec = (struct snd_codec *)
4306 calloc(1, sizeof(struct snd_codec));
4307
4308 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004309
4310 out->stream.set_callback = out_set_callback;
4311 out->stream.pause = out_pause;
4312 out->stream.resume = out_resume;
4313 out->stream.drain = out_drain;
4314 out->stream.flush = out_flush;
4315
4316 out->compr_config.codec->id =
4317 get_snd_codec_id(config->offload_info.format);
4318 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4319 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004320 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004321 out->compr_config.codec->bit_rate =
4322 config->offload_info.bit_rate;
4323 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004324 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4326
4327 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4328 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004329
4330 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004331 create_offload_callback_thread(out);
4332 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4333 __func__, config->offload_info.version,
4334 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004335 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4336 switch (config->sample_rate) {
4337 case 0:
4338 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4339 break;
4340 case 8000:
4341 case 16000:
4342 case 48000:
4343 out->sample_rate = config->sample_rate;
4344 break;
4345 default:
4346 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4347 config->sample_rate);
4348 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4349 ret = -EINVAL;
4350 goto error_open;
4351 }
4352 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4353 switch (config->channel_mask) {
4354 case AUDIO_CHANNEL_NONE:
4355 case AUDIO_CHANNEL_OUT_STEREO:
4356 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4357 break;
4358 default:
4359 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4360 config->channel_mask);
4361 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4362 ret = -EINVAL;
4363 goto error_open;
4364 }
4365 switch (config->format) {
4366 case AUDIO_FORMAT_DEFAULT:
4367 case AUDIO_FORMAT_PCM_16_BIT:
4368 out->format = AUDIO_FORMAT_PCM_16_BIT;
4369 break;
4370 default:
4371 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4372 config->format);
4373 config->format = AUDIO_FORMAT_PCM_16_BIT;
4374 ret = -EINVAL;
4375 goto error_open;
4376 }
4377
4378 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004379 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004380 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004381 case 0:
4382 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4383 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004384 case 8000:
4385 case 16000:
4386 case 48000:
4387 out->sample_rate = config->sample_rate;
4388 break;
4389 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004390 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4391 config->sample_rate);
4392 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4393 ret = -EINVAL;
4394 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004395 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004396 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4397 switch (config->channel_mask) {
4398 case AUDIO_CHANNEL_NONE:
4399 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4400 break;
4401 case AUDIO_CHANNEL_OUT_STEREO:
4402 out->channel_mask = config->channel_mask;
4403 break;
4404 default:
4405 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4406 config->channel_mask);
4407 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4408 ret = -EINVAL;
4409 break;
4410 }
4411 switch (config->format) {
4412 case AUDIO_FORMAT_DEFAULT:
4413 out->format = AUDIO_FORMAT_PCM_16_BIT;
4414 break;
4415 case AUDIO_FORMAT_PCM_16_BIT:
4416 out->format = config->format;
4417 break;
4418 default:
4419 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4420 config->format);
4421 config->format = AUDIO_FORMAT_PCM_16_BIT;
4422 ret = -EINVAL;
4423 break;
4424 }
4425 if (ret != 0)
4426 goto error_open;
4427
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004428 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4429 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004430 out->config.rate = out->sample_rate;
4431 out->config.channels =
4432 audio_channel_count_from_out_mask(out->channel_mask);
4433 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004434 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004435 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4436 switch (config->sample_rate) {
4437 case 0:
4438 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4439 break;
4440 case 8000:
4441 case 16000:
4442 case 32000:
4443 case 48000:
4444 out->sample_rate = config->sample_rate;
4445 break;
4446 default:
4447 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4448 config->sample_rate);
4449 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4450 ret = -EINVAL;
4451 break;
4452 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004453 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004454 switch (config->channel_mask) {
4455 case AUDIO_CHANNEL_NONE:
4456 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4457 break;
4458 case AUDIO_CHANNEL_OUT_STEREO:
4459 out->channel_mask = config->channel_mask;
4460 break;
4461 default:
4462 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4463 config->channel_mask);
4464 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4465 ret = -EINVAL;
4466 break;
4467 }
4468 switch (config->format) {
4469 case AUDIO_FORMAT_DEFAULT:
4470 out->format = AUDIO_FORMAT_PCM_16_BIT;
4471 break;
4472 case AUDIO_FORMAT_PCM_16_BIT:
4473 out->format = config->format;
4474 break;
4475 default:
4476 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4477 config->format);
4478 config->format = AUDIO_FORMAT_PCM_16_BIT;
4479 ret = -EINVAL;
4480 break;
4481 }
4482 if (ret != 0)
4483 goto error_open;
4484
vivek mehtaa68fea62017-06-08 19:04:02 -07004485 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004486 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4487 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004488 out->config.rate = out->sample_rate;
4489 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004490 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004491 out->sample_rate,
4492 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004493 out->config.channels,
4494 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004495 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004496 out->config.period_size = buffer_size / frame_size;
4497 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4498 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004499 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004500 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004501 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4502 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004503 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004504 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4505 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004506 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004507 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004508 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004509 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004510 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004511 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4512 out->config = pcm_config_mmap_playback;
4513 out->stream.start = out_start;
4514 out->stream.stop = out_stop;
4515 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4516 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004517 } else {
4518 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4519 out->config = pcm_config_low_latency;
4520 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004521
4522 if (config->sample_rate == 0) {
4523 out->sample_rate = out->config.rate;
4524 } else {
4525 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004526 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004527 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4528 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4529 } else {
4530 out->channel_mask = config->channel_mask;
4531 }
4532 if (config->format == AUDIO_FORMAT_DEFAULT)
4533 out->format = audio_format_from_pcm_format(out->config.format);
4534 else if (!audio_is_linear_pcm(config->format)) {
4535 config->format = AUDIO_FORMAT_PCM_16_BIT;
4536 ret = -EINVAL;
4537 goto error_open;
4538 } else {
4539 out->format = config->format;
4540 }
4541
4542 out->config.rate = out->sample_rate;
4543 out->config.channels =
4544 audio_channel_count_from_out_mask(out->channel_mask);
4545 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4546 out->config.format = pcm_format_from_audio_format(out->format);
4547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004548 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004549
4550 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4551 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004552 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004553 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4554 __func__, config->sample_rate, config->format, config->channel_mask);
4555 config->sample_rate = out->sample_rate;
4556 config->format = out->format;
4557 config->channel_mask = out->channel_mask;
4558 ret = -EINVAL;
4559 goto error_open;
4560 }
4561
Andy Hung6fcba9c2014-03-18 11:53:32 -07004562 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4563 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004565 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004566 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004567 adev->primary_output = out;
4568 else {
4569 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004570 ret = -EEXIST;
4571 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004572 }
4573 }
4574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004575 /* Check if this usecase is already existing */
4576 pthread_mutex_lock(&adev->lock);
4577 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4578 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004580 ret = -EEXIST;
4581 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582 }
4583 pthread_mutex_unlock(&adev->lock);
4584
4585 out->stream.common.get_sample_rate = out_get_sample_rate;
4586 out->stream.common.set_sample_rate = out_set_sample_rate;
4587 out->stream.common.get_buffer_size = out_get_buffer_size;
4588 out->stream.common.get_channels = out_get_channels;
4589 out->stream.common.get_format = out_get_format;
4590 out->stream.common.set_format = out_set_format;
4591 out->stream.common.standby = out_standby;
4592 out->stream.common.dump = out_dump;
4593 out->stream.common.set_parameters = out_set_parameters;
4594 out->stream.common.get_parameters = out_get_parameters;
4595 out->stream.common.add_audio_effect = out_add_audio_effect;
4596 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4597 out->stream.get_latency = out_get_latency;
4598 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004599#ifdef NO_AUDIO_OUT
4600 out->stream.write = out_write_for_no_output;
4601#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004603#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004604 out->stream.get_render_position = out_get_render_position;
4605 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004606 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607
Eric Laurent0e46adf2016-12-16 12:49:24 -08004608 if (out->realtime)
4609 out->af_period_multiplier = af_period_multiplier;
4610 else
4611 out->af_period_multiplier = 1;
4612
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004613 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004614 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004615 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004617 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004618 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004619 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004621 config->format = out->stream.common.get_format(&out->stream.common);
4622 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4623 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4624
Kevin Rocarda325aa22018-04-03 09:15:52 -07004625 register_format(out->format, out->supported_formats);
4626 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4627 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4628
Andy Hunga452b0a2017-03-15 14:51:15 -07004629 out->error_log = error_log_create(
4630 ERROR_LOG_ENTRIES,
4631 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4632
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004633 /*
4634 By locking output stream before registering, we allow the callback
4635 to update stream's state only after stream's initial state is set to
4636 adev state.
4637 */
4638 lock_output_stream(out);
4639 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4640 pthread_mutex_lock(&adev->lock);
4641 out->card_status = adev->card_status;
4642 pthread_mutex_unlock(&adev->lock);
4643 pthread_mutex_unlock(&out->lock);
4644
vivek mehta4a824772017-06-08 19:05:49 -07004645 stream_app_type_cfg_init(&out->app_type_cfg);
4646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004648
Eric Laurent994a6932013-07-17 11:51:42 -07004649 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004651
4652error_open:
4653 free(out);
4654 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004655 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004656 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657}
4658
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004659static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660 struct audio_stream_out *stream)
4661{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004662 struct stream_out *out = (struct stream_out *)stream;
4663 struct audio_device *adev = out->dev;
4664
Eric Laurent994a6932013-07-17 11:51:42 -07004665 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004666
4667 // must deregister from sndmonitor first to prevent races
4668 // between the callback and close_stream
4669 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004671 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4672 destroy_offload_callback_thread(out);
4673
4674 if (out->compr_config.codec != NULL)
4675 free(out->compr_config.codec);
4676 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004677
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004678 out->a2dp_compress_mute = false;
4679
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004680 if (adev->voice_tx_output == out)
4681 adev->voice_tx_output = NULL;
4682
Andy Hunga452b0a2017-03-15 14:51:15 -07004683 error_log_destroy(out->error_log);
4684 out->error_log = NULL;
4685
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004686 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004687 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004688 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004690 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691}
4692
4693static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4694{
4695 struct audio_device *adev = (struct audio_device *)dev;
4696 struct str_parms *parms;
4697 char *str;
4698 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004699 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004700 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004701 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004702 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703
Joe Onorato188b6222016-03-01 11:02:27 -08004704 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004705
4706 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
4708 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004709 status = voice_set_parameters(adev, parms);
4710 if (status != 0) {
4711 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004712 }
4713
4714 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4715 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004716 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004717 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4718 adev->bluetooth_nrec = true;
4719 else
4720 adev->bluetooth_nrec = false;
4721 }
4722
4723 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4724 if (ret >= 0) {
4725 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4726 adev->screen_off = false;
4727 else
4728 adev->screen_off = true;
4729 }
4730
jasmine cha270b7762018-03-30 15:41:33 +08004731#ifndef MAXXAUDIO_QDSP_ENABLED
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004732 ret = str_parms_get_int(parms, "rotation", &val);
4733 if (ret >= 0) {
4734 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004735 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004736 // FIXME: note that the code below assumes that the speakers are in the correct placement
4737 // relative to the user when the device is rotated 90deg from its default rotation. This
4738 // assumption is device-specific, not platform-specific like this code.
4739 case 270:
4740 reverse_speakers = true;
4741 break;
4742 case 0:
4743 case 90:
4744 case 180:
4745 break;
4746 default:
4747 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004748 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004749 }
Eric Laurent03f09432014-03-25 18:09:11 -07004750 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004751 // check and set swap
4752 // - check if orientation changed and speaker active
4753 // - set rotation and cache the rotation value
4754 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004755 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004756 }
jasmine cha270b7762018-03-30 15:41:33 +08004757#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004758
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004759 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4760 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004761 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004762 }
4763
David Linee3fe402017-03-13 10:00:42 -07004764 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4765 if (ret >= 0) {
4766 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004767 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004768 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4769 if (ret >= 0) {
4770 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004771 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004772 }
Eric Laurent99dab492017-06-17 15:19:08 -07004773 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004774 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4775 if (ret >= 0) {
4776 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004777 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004778 }
4779 }
4780 }
4781
4782 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4783 if (ret >= 0) {
4784 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004785 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004786 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4787 if (ret >= 0) {
4788 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004789 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004790 }
Eric Laurent99dab492017-06-17 15:19:08 -07004791 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004792 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4793 if (ret >= 0) {
4794 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004795 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004796 }
4797 }
4798 }
4799
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004800 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08004801 audio_extn_ma_set_parameters(adev, parms);
4802
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004803 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
4804 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004805 struct audio_usecase *usecase;
4806 struct listnode *node;
4807 list_for_each(node, &adev->usecase_list) {
4808 usecase = node_to_item(node, struct audio_usecase, list);
4809 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004810 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004811 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4812
4813 pthread_mutex_unlock(&adev->lock);
4814 lock_output_stream(usecase->stream.out);
4815 pthread_mutex_lock(&adev->lock);
4816 audio_extn_a2dp_set_handoff_mode(true);
4817 // force device switch to reconfigure encoder
4818 select_devices(adev, usecase->id);
4819 audio_extn_a2dp_set_handoff_mode(false);
4820 pthread_mutex_unlock(&usecase->stream.out->lock);
4821 break;
4822 }
4823 }
4824 }
4825
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004826done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004828 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004829 ALOGV("%s: exit with code(%d)", __func__, status);
4830 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831}
4832
4833static char* adev_get_parameters(const struct audio_hw_device *dev,
4834 const char *keys)
4835{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004836 struct audio_device *adev = (struct audio_device *)dev;
4837 struct str_parms *reply = str_parms_create();
4838 struct str_parms *query = str_parms_create_str(keys);
4839 char *str;
4840
4841 pthread_mutex_lock(&adev->lock);
4842
4843 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004844 audio_extn_a2dp_get_parameters(query, reply);
4845
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004846 str = str_parms_to_str(reply);
4847 str_parms_destroy(query);
4848 str_parms_destroy(reply);
4849
4850 pthread_mutex_unlock(&adev->lock);
4851 ALOGV("%s: exit: returns - %s", __func__, str);
4852 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853}
4854
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004855static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856{
4857 return 0;
4858}
4859
Haynes Mathew George5191a852013-09-11 14:19:36 -07004860static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4861{
4862 int ret;
4863 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004864
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004865 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4866
Haynes Mathew George5191a852013-09-11 14:19:36 -07004867 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004868 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004869 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004870
Haynes Mathew George5191a852013-09-11 14:19:36 -07004871 return ret;
4872}
4873
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004874static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875{
4876 return -ENOSYS;
4877}
4878
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004879static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4880 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004881{
4882 return -ENOSYS;
4883}
4884
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004885static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886{
4887 return -ENOSYS;
4888}
4889
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004890static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891{
4892 return -ENOSYS;
4893}
4894
4895static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4896{
4897 struct audio_device *adev = (struct audio_device *)dev;
4898
4899 pthread_mutex_lock(&adev->lock);
4900 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004901 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004903 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4904 voice_is_in_call(adev)) {
4905 voice_stop_call(adev);
4906 adev->current_call_output = NULL;
4907 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908 }
4909 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004910
4911 audio_extn_extspk_set_mode(adev->extspk, mode);
4912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004913 return 0;
4914}
4915
4916static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4917{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004918 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920
Eric Laurent2bafff12016-03-17 12:17:23 -07004921 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004922 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004923 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4924 ret = audio_extn_hfp_set_mic_mute(adev, state);
4925 } else {
4926 ret = voice_set_mic_mute(adev, state);
4927 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004928 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004929 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004930
4931 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004932}
4933
4934static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4935{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004936 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004937 return 0;
4938}
4939
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004940static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941 const struct audio_config *config)
4942{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004943 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944
Eric Laurent74b55762017-07-09 17:04:53 -07004945 /* Don't know if USB HIFI in this context so use true to be conservative */
4946 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4947 true /*is_usb_hifi */) != 0)
4948 return 0;
4949
vivek mehtaa68fea62017-06-08 19:04:02 -07004950 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4951 config->sample_rate, config->format,
4952 channel_count,
4953 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004954}
4955
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004956static bool adev_input_allow_hifi_record(struct audio_device *adev,
4957 audio_devices_t devices,
4958 audio_input_flags_t flags,
4959 audio_source_t source) {
4960 const bool allowed = true;
4961
4962 if (!audio_is_usb_in_device(devices))
4963 return !allowed;
4964
4965 switch (flags) {
4966 case AUDIO_INPUT_FLAG_NONE:
4967 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4968 break;
4969 default:
4970 return !allowed;
4971 }
4972
4973 switch (source) {
4974 case AUDIO_SOURCE_DEFAULT:
4975 case AUDIO_SOURCE_MIC:
4976 case AUDIO_SOURCE_UNPROCESSED:
4977 break;
4978 default:
4979 return !allowed;
4980 }
4981
4982 switch (adev->mode) {
4983 case 0:
4984 break;
4985 default:
4986 return !allowed;
4987 }
4988
4989 return allowed;
4990}
4991
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004993 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004994 audio_devices_t devices,
4995 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004996 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004997 audio_input_flags_t flags,
4998 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004999 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000{
5001 struct audio_device *adev = (struct audio_device *)dev;
5002 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005003 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005004 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005005 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005006 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005007 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5008 devices,
5009 flags,
5010 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005011 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5012 " sample_rate %u, channel_mask %#x, format %#x",
5013 __func__, flags, is_usb_dev, may_use_hifi_record,
5014 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005016
Andy Hungd9653bd2017-08-01 19:31:39 -07005017 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5018 return -ENOSYS;
5019 }
5020
Eric Laurent74b55762017-07-09 17:04:53 -07005021 if (!(is_usb_dev && may_use_hifi_record)) {
5022 if (config->sample_rate == 0)
5023 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5024 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5025 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5026 if (config->format == AUDIO_FORMAT_DEFAULT)
5027 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005028
Eric Laurent74b55762017-07-09 17:04:53 -07005029 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5030
5031 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5032 return -EINVAL;
5033 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005035 if (audio_extn_tfa_98xx_is_supported() &&
5036 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005037 return -EINVAL;
5038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005039 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5040
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005041 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005042 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 in->stream.common.get_sample_rate = in_get_sample_rate;
5045 in->stream.common.set_sample_rate = in_set_sample_rate;
5046 in->stream.common.get_buffer_size = in_get_buffer_size;
5047 in->stream.common.get_channels = in_get_channels;
5048 in->stream.common.get_format = in_get_format;
5049 in->stream.common.set_format = in_set_format;
5050 in->stream.common.standby = in_standby;
5051 in->stream.common.dump = in_dump;
5052 in->stream.common.set_parameters = in_set_parameters;
5053 in->stream.common.get_parameters = in_get_parameters;
5054 in->stream.common.add_audio_effect = in_add_audio_effect;
5055 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5056 in->stream.set_gain = in_set_gain;
5057 in->stream.read = in_read;
5058 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005059 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005060 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061
5062 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005063 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005064 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005065 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005066 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005067 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005068
Andy Hung88ce1d92018-10-29 18:31:12 -07005069 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005070 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5071 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5072 /* Force channel config requested to mono if incall
5073 record is being requested for only uplink/downlink */
5074 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5075 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5076 ret = -EINVAL;
5077 goto err_open;
5078 }
5079 }
5080
Haynes Mathew George569b7482017-05-08 14:44:27 -07005081 if (is_usb_dev && may_use_hifi_record) {
5082 /* HiFi record selects an appropriate format, channel, rate combo
5083 depending on sink capabilities*/
5084 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5085 &config->format,
5086 &in->supported_formats[0],
5087 MAX_SUPPORTED_FORMATS,
5088 &config->channel_mask,
5089 &in->supported_channel_masks[0],
5090 MAX_SUPPORTED_CHANNEL_MASKS,
5091 &config->sample_rate,
5092 &in->supported_sample_rates[0],
5093 MAX_SUPPORTED_SAMPLE_RATES);
5094 if (ret != 0) {
5095 ret = -EINVAL;
5096 goto err_open;
5097 }
Eric Laurent74b55762017-07-09 17:04:53 -07005098 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005099 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005100 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005101 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5102 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5103 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5104 bool ret_error = false;
5105 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5106 from HAL is 8_24
5107 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5108 8_24 return error indicating supported format is 8_24
5109 *> In case of any other source requesting 24 bit or float return error
5110 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005111
vivek mehta57ff9b52016-04-28 14:13:08 -07005112 on error flinger will retry with supported format passed
5113 */
5114 if (source != AUDIO_SOURCE_UNPROCESSED) {
5115 config->format = AUDIO_FORMAT_PCM_16_BIT;
5116 ret_error = true;
5117 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5118 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5119 ret_error = true;
5120 }
5121
5122 if (ret_error) {
5123 ret = -EINVAL;
5124 goto err_open;
5125 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005126 }
5127
vivek mehta57ff9b52016-04-28 14:13:08 -07005128 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005129 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005132 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5133 if (config->sample_rate == 0)
5134 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5135 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5136 config->sample_rate != 8000) {
5137 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5138 ret = -EINVAL;
5139 goto err_open;
5140 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005141
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005142 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5143 config->format = AUDIO_FORMAT_PCM_16_BIT;
5144 ret = -EINVAL;
5145 goto err_open;
5146 }
5147
5148 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5149 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005150 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005151 } else if (is_usb_dev && may_use_hifi_record) {
5152 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5153 in->config = pcm_config_audio_capture;
5154 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005155 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5156 config->sample_rate,
5157 config->format,
5158 channel_count,
5159 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005160 in->config.period_size = buffer_size / frame_size;
5161 in->config.rate = config->sample_rate;
5162 in->af_period_multiplier = 1;
5163 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005164 } else {
5165 in->usecase = USECASE_AUDIO_RECORD;
5166 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005167 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005168 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005169#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005170 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005171#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005172 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005173 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005174 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005175 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005176 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5177 config->sample_rate,
5178 config->format,
5179 channel_count,
5180 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005181 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005182 in->config.rate = config->sample_rate;
5183 in->af_period_multiplier = 1;
5184 } else {
5185 // period size is left untouched for rt mode playback
5186 in->config = pcm_config_audio_capture_rt;
5187 in->af_period_multiplier = af_period_multiplier;
5188 }
5189 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5190 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005191 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005192 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5193 in->config = pcm_config_mmap_capture;
5194 in->stream.start = in_start;
5195 in->stream.stop = in_stop;
5196 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5197 in->stream.get_mmap_position = in_get_mmap_position;
5198 in->af_period_multiplier = 1;
5199 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005200 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005201 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005202 (config->sample_rate == 8000 ||
5203 config->sample_rate == 16000 ||
5204 config->sample_rate == 32000 ||
5205 config->sample_rate == 48000) &&
5206 channel_count == 1) {
5207 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5208 in->config = pcm_config_audio_capture;
5209 frame_size = audio_stream_in_frame_size(&in->stream);
5210 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5211 config->sample_rate,
5212 config->format,
5213 channel_count, false /*is_low_latency*/);
5214 in->config.period_size = buffer_size / frame_size;
5215 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5216 in->config.rate = config->sample_rate;
5217 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005218 } else {
5219 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005220 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005221 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5222 config->sample_rate,
5223 config->format,
5224 channel_count,
5225 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005226 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005227 in->config.rate = config->sample_rate;
5228 in->af_period_multiplier = 1;
5229 }
5230 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5231 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005232 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005234 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005235 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236
Kevin Rocarda325aa22018-04-03 09:15:52 -07005237
5238 register_format(in->format, in->supported_formats);
5239 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5240 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5241
Andy Hungd13f0d32017-06-12 13:58:37 -07005242 in->error_log = error_log_create(
5243 ERROR_LOG_ENTRIES,
5244 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5245
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005246 /* This stream could be for sound trigger lab,
5247 get sound trigger pcm if present */
5248 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005250 lock_input_stream(in);
5251 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5252 pthread_mutex_lock(&adev->lock);
5253 in->card_status = adev->card_status;
5254 pthread_mutex_unlock(&adev->lock);
5255 pthread_mutex_unlock(&in->lock);
5256
vivek mehta4a824772017-06-08 19:05:49 -07005257 stream_app_type_cfg_init(&in->app_type_cfg);
5258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005259 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005260 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005261 return 0;
5262
5263err_open:
5264 free(in);
5265 *stream_in = NULL;
5266 return ret;
5267}
5268
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005269static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 struct audio_stream_in *stream)
5271{
Andy Hungd13f0d32017-06-12 13:58:37 -07005272 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005273 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005274
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005275 // must deregister from sndmonitor first to prevent races
5276 // between the callback and close_stream
5277 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005279
5280 error_log_destroy(in->error_log);
5281 in->error_log = NULL;
5282
Andy Hung0dbb52b2017-08-09 13:51:38 -07005283 pthread_mutex_destroy(&in->pre_lock);
5284 pthread_mutex_destroy(&in->lock);
5285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005286 free(stream);
5287
5288 return;
5289}
5290
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005291static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292{
5293 return 0;
5294}
5295
Andy Hung31aca912014-03-20 17:14:59 -07005296/* verifies input and output devices and their capabilities.
5297 *
5298 * This verification is required when enabling extended bit-depth or
5299 * sampling rates, as not all qcom products support it.
5300 *
5301 * Suitable for calling only on initialization such as adev_open().
5302 * It fills the audio_device use_case_table[] array.
5303 *
5304 * Has a side-effect that it needs to configure audio routing / devices
5305 * in order to power up the devices and read the device parameters.
5306 * It does not acquire any hw device lock. Should restore the devices
5307 * back to "normal state" upon completion.
5308 */
5309static int adev_verify_devices(struct audio_device *adev)
5310{
5311 /* enumeration is a bit difficult because one really wants to pull
5312 * the use_case, device id, etc from the hidden pcm_device_table[].
5313 * In this case there are the following use cases and device ids.
5314 *
5315 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5316 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005317 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005318 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5319 * [USECASE_AUDIO_RECORD] = {0, 0},
5320 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5321 * [USECASE_VOICE_CALL] = {2, 2},
5322 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005323 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005324 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5325 */
5326
5327 /* should be the usecases enabled in adev_open_input_stream() */
5328 static const int test_in_usecases[] = {
5329 USECASE_AUDIO_RECORD,
5330 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5331 };
5332 /* should be the usecases enabled in adev_open_output_stream()*/
5333 static const int test_out_usecases[] = {
5334 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5335 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5336 };
5337 static const usecase_type_t usecase_type_by_dir[] = {
5338 PCM_PLAYBACK,
5339 PCM_CAPTURE,
5340 };
5341 static const unsigned flags_by_dir[] = {
5342 PCM_OUT,
5343 PCM_IN,
5344 };
5345
5346 size_t i;
5347 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005348 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005349 char info[512]; /* for possible debug info */
5350
5351 for (dir = 0; dir < 2; ++dir) {
5352 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5353 const unsigned flags_dir = flags_by_dir[dir];
5354 const size_t testsize =
5355 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5356 const int *testcases =
5357 dir ? test_in_usecases : test_out_usecases;
5358 const audio_devices_t audio_device =
5359 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5360
5361 for (i = 0; i < testsize; ++i) {
5362 const audio_usecase_t audio_usecase = testcases[i];
5363 int device_id;
5364 snd_device_t snd_device;
5365 struct pcm_params **pparams;
5366 struct stream_out out;
5367 struct stream_in in;
5368 struct audio_usecase uc_info;
5369 int retval;
5370
5371 pparams = &adev->use_case_table[audio_usecase];
5372 pcm_params_free(*pparams); /* can accept null input */
5373 *pparams = NULL;
5374
5375 /* find the device ID for the use case (signed, for error) */
5376 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5377 if (device_id < 0)
5378 continue;
5379
5380 /* prepare structures for device probing */
5381 memset(&uc_info, 0, sizeof(uc_info));
5382 uc_info.id = audio_usecase;
5383 uc_info.type = usecase_type;
5384 if (dir) {
5385 adev->active_input = &in;
5386 memset(&in, 0, sizeof(in));
5387 in.device = audio_device;
5388 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5389 uc_info.stream.in = &in;
5390 } else {
5391 adev->active_input = NULL;
5392 }
5393 memset(&out, 0, sizeof(out));
5394 out.devices = audio_device; /* only field needed in select_devices */
5395 uc_info.stream.out = &out;
5396 uc_info.devices = audio_device;
5397 uc_info.in_snd_device = SND_DEVICE_NONE;
5398 uc_info.out_snd_device = SND_DEVICE_NONE;
5399 list_add_tail(&adev->usecase_list, &uc_info.list);
5400
5401 /* select device - similar to start_(in/out)put_stream() */
5402 retval = select_devices(adev, audio_usecase);
5403 if (retval >= 0) {
5404 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5405#if LOG_NDEBUG == 0
5406 if (*pparams) {
5407 ALOGV("%s: (%s) card %d device %d", __func__,
5408 dir ? "input" : "output", card_id, device_id);
5409 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005410 } else {
5411 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5412 }
5413#endif
5414 }
5415
5416 /* deselect device - similar to stop_(in/out)put_stream() */
5417 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005418 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005419 /* 2. Disable the rx device */
5420 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005421 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005422 list_remove(&uc_info.list);
5423 }
5424 }
5425 adev->active_input = NULL; /* restore adev state */
5426 return 0;
5427}
5428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005429static int adev_close(hw_device_t *device)
5430{
Andy Hung31aca912014-03-20 17:14:59 -07005431 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005433
5434 if (!adev)
5435 return 0;
5436
5437 pthread_mutex_lock(&adev_init_lock);
5438
5439 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005440 audio_extn_snd_mon_unregister_listener(adev);
5441 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005442 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005443 audio_route_free(adev->audio_route);
5444 free(adev->snd_dev_ref_cnt);
5445 platform_deinit(adev->platform);
5446 audio_extn_extspk_deinit(adev->extspk);
5447 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005448 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005449 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5450 pcm_params_free(adev->use_case_table[i]);
5451 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005452 if (adev->adm_deinit)
5453 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005454 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005455 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005456 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005457
5458 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460 return 0;
5461}
5462
Glenn Kasten4f993392014-05-14 07:30:48 -07005463/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5464 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5465 * just that it _might_ work.
5466 */
5467static int period_size_is_plausible_for_low_latency(int period_size)
5468{
5469 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005470 case 48:
5471 case 96:
5472 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005473 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005474 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005475 case 240:
5476 case 320:
5477 case 480:
5478 return 1;
5479 default:
5480 return 0;
5481 }
5482}
5483
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005484static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5485{
5486 int card;
5487 card_status_t status;
5488
5489 if (!parms)
5490 return;
5491
5492 if (parse_snd_card_status(parms, &card, &status) < 0)
5493 return;
5494
5495 pthread_mutex_lock(&adev->lock);
5496 bool valid_cb = (card == adev->snd_card);
5497 if (valid_cb) {
5498 if (adev->card_status != status) {
5499 adev->card_status = status;
5500 platform_snd_card_update(adev->platform, status);
5501 }
5502 }
5503 pthread_mutex_unlock(&adev->lock);
5504 return;
5505}
5506
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005507/* out and adev lock held */
5508static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5509{
5510 struct audio_usecase *uc_info;
5511 float left_p;
5512 float right_p;
5513 audio_devices_t devices;
5514
5515 uc_info = get_usecase_from_list(adev, out->usecase);
5516 if (uc_info == NULL) {
5517 ALOGE("%s: Could not find the usecase (%d) in the list",
5518 __func__, out->usecase);
5519 return -EINVAL;
5520 }
5521
5522 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5523 out->usecase, use_case_table[out->usecase]);
5524
5525 if (restore) {
5526 // restore A2DP device for active usecases and unmute if required
5527 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5528 !is_a2dp_device(uc_info->out_snd_device)) {
5529 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5530 select_devices(adev, uc_info->id);
5531 pthread_mutex_lock(&out->compr_mute_lock);
5532 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5533 (out->a2dp_compress_mute)) {
5534 out->a2dp_compress_mute = false;
5535 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5536 }
5537 pthread_mutex_unlock(&out->compr_mute_lock);
5538 }
5539 } else {
5540 // mute compress stream if suspended
5541 pthread_mutex_lock(&out->compr_mute_lock);
5542 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5543 (!out->a2dp_compress_mute)) {
5544 if (!out->standby) {
5545 ALOGD("%s: selecting speaker and muting stream", __func__);
5546 devices = out->devices;
5547 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5548 left_p = out->volume_l;
5549 right_p = out->volume_r;
5550 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5551 compress_pause(out->compr);
5552 set_compr_volume(&out->stream, 0.0f, 0.0f);
5553 out->a2dp_compress_mute = true;
5554 select_devices(adev, out->usecase);
5555 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5556 compress_resume(out->compr);
5557 out->devices = devices;
5558 out->volume_l = left_p;
5559 out->volume_r = right_p;
5560 }
5561 }
5562 pthread_mutex_unlock(&out->compr_mute_lock);
5563 }
5564 ALOGV("%s: exit", __func__);
5565 return 0;
5566}
5567
5568int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5569{
5570 int ret = 0;
5571
5572 lock_output_stream(out);
5573 pthread_mutex_lock(&adev->lock);
5574
5575 ret = check_a2dp_restore_l(adev, out, restore);
5576
5577 pthread_mutex_unlock(&adev->lock);
5578 pthread_mutex_unlock(&out->lock);
5579 return ret;
5580}
5581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005582static int adev_open(const hw_module_t *module, const char *name,
5583 hw_device_t **device)
5584{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005585 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005586
Eric Laurent2bafff12016-03-17 12:17:23 -07005587 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005588 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005589 pthread_mutex_lock(&adev_init_lock);
5590 if (audio_device_ref_count != 0) {
5591 *device = &adev->device.common;
5592 audio_device_ref_count++;
5593 ALOGV("%s: returning existing instance of adev", __func__);
5594 ALOGV("%s: exit", __func__);
5595 pthread_mutex_unlock(&adev_init_lock);
5596 return 0;
5597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598 adev = calloc(1, sizeof(struct audio_device));
5599
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005600 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5603 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5604 adev->device.common.module = (struct hw_module_t *)module;
5605 adev->device.common.close = adev_close;
5606
5607 adev->device.init_check = adev_init_check;
5608 adev->device.set_voice_volume = adev_set_voice_volume;
5609 adev->device.set_master_volume = adev_set_master_volume;
5610 adev->device.get_master_volume = adev_get_master_volume;
5611 adev->device.set_master_mute = adev_set_master_mute;
5612 adev->device.get_master_mute = adev_get_master_mute;
5613 adev->device.set_mode = adev_set_mode;
5614 adev->device.set_mic_mute = adev_set_mic_mute;
5615 adev->device.get_mic_mute = adev_get_mic_mute;
5616 adev->device.set_parameters = adev_set_parameters;
5617 adev->device.get_parameters = adev_get_parameters;
5618 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5619 adev->device.open_output_stream = adev_open_output_stream;
5620 adev->device.close_output_stream = adev_close_output_stream;
5621 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005622
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623 adev->device.close_input_stream = adev_close_input_stream;
5624 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005625 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005626
5627 /* Set the default route before the PCM stream is opened */
5628 pthread_mutex_lock(&adev->lock);
5629 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005630 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005631 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005633 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005634 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005635 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005636 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005637 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005638 pthread_mutex_unlock(&adev->lock);
5639
5640 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005641 adev->platform = platform_init(adev);
5642 if (!adev->platform) {
5643 free(adev->snd_dev_ref_cnt);
5644 free(adev);
5645 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5646 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005647 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005648 return -EINVAL;
5649 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005650 adev->extspk = audio_extn_extspk_init(adev);
5651
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005652 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5653 if (adev->visualizer_lib == NULL) {
5654 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5655 } else {
5656 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5657 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005658 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005659 "visualizer_hal_start_output");
5660 adev->visualizer_stop_output =
5661 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5662 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005663 }
5664
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005665 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5666 if (adev->offload_effects_lib == NULL) {
5667 ALOGW("%s: DLOPEN failed for %s", __func__,
5668 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5669 } else {
5670 ALOGV("%s: DLOPEN successful for %s", __func__,
5671 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5672 adev->offload_effects_start_output =
5673 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5674 "offload_effects_bundle_hal_start_output");
5675 adev->offload_effects_stop_output =
5676 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5677 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005678 }
5679
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005680 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5681 if (adev->adm_lib == NULL) {
5682 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5683 } else {
5684 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5685 adev->adm_init = (adm_init_t)
5686 dlsym(adev->adm_lib, "adm_init");
5687 adev->adm_deinit = (adm_deinit_t)
5688 dlsym(adev->adm_lib, "adm_deinit");
5689 adev->adm_register_input_stream = (adm_register_input_stream_t)
5690 dlsym(adev->adm_lib, "adm_register_input_stream");
5691 adev->adm_register_output_stream = (adm_register_output_stream_t)
5692 dlsym(adev->adm_lib, "adm_register_output_stream");
5693 adev->adm_deregister_stream = (adm_deregister_stream_t)
5694 dlsym(adev->adm_lib, "adm_deregister_stream");
5695 adev->adm_request_focus = (adm_request_focus_t)
5696 dlsym(adev->adm_lib, "adm_request_focus");
5697 adev->adm_abandon_focus = (adm_abandon_focus_t)
5698 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005699 adev->adm_set_config = (adm_set_config_t)
5700 dlsym(adev->adm_lib, "adm_set_config");
5701 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5702 dlsym(adev->adm_lib, "adm_request_focus_v2");
5703 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5704 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5705 adev->adm_on_routing_change = (adm_on_routing_change_t)
5706 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005707 }
5708
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005709 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005710 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005712 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005713
Andy Hung31aca912014-03-20 17:14:59 -07005714 if (k_enable_extended_precision)
5715 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005716
Glenn Kasten4f993392014-05-14 07:30:48 -07005717 char value[PROPERTY_VALUE_MAX];
5718 int trial;
5719 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5720 trial = atoi(value);
5721 if (period_size_is_plausible_for_low_latency(trial)) {
5722 pcm_config_low_latency.period_size = trial;
5723 pcm_config_low_latency.start_threshold = trial / 4;
5724 pcm_config_low_latency.avail_min = trial / 4;
5725 configured_low_latency_capture_period_size = trial;
5726 }
5727 }
5728 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5729 trial = atoi(value);
5730 if (period_size_is_plausible_for_low_latency(trial)) {
5731 configured_low_latency_capture_period_size = trial;
5732 }
5733 }
5734
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07005735 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
5736
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005737 // commented as full set of app type cfg is sent from platform
5738 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005739 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005740
5741 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5742 af_period_multiplier = atoi(value);
5743 if (af_period_multiplier < 0) {
5744 af_period_multiplier = 2;
5745 } else if (af_period_multiplier > 4) {
5746 af_period_multiplier = 4;
5747 }
5748 ALOGV("new period_multiplier = %d", af_period_multiplier);
5749 }
5750
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005751 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08005752 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005753
vivek mehta1a9b7c02015-06-25 11:49:38 -07005754 pthread_mutex_unlock(&adev_init_lock);
5755
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005756 if (adev->adm_init)
5757 adev->adm_data = adev->adm_init();
5758
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005759 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005760 audio_extn_snd_mon_init();
5761 pthread_mutex_lock(&adev->lock);
5762 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5763 adev->card_status = CARD_STATUS_ONLINE;
5764 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005765 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005766
Eric Laurent2bafff12016-03-17 12:17:23 -07005767 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005768 return 0;
5769}
5770
5771static struct hw_module_methods_t hal_module_methods = {
5772 .open = adev_open,
5773};
5774
5775struct audio_module HAL_MODULE_INFO_SYM = {
5776 .common = {
5777 .tag = HARDWARE_MODULE_TAG,
5778 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5779 .hal_api_version = HARDWARE_HAL_API_VERSION,
5780 .id = AUDIO_HARDWARE_MODULE_ID,
5781 .name = "QCOM Audio HAL",
5782 .author = "Code Aurora Forum",
5783 .methods = &hal_module_methods,
5784 },
5785};