blob: d54e397be50febaf8f686c99cb59f477af62dafd [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080046#include <processgroup/sched_policy.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080061#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062
Eric Laurent397db572016-05-11 11:31:47 -070063/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
64 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070065#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070066// 2 buffers causes problems with high bitrate files
67#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070068/* ToDo: Check and update a proper value in msec */
69#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070070/* treat as unsigned Q1.13 */
71#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070072#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070073
74/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070075#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076
Eric Laurent51f3c662018-04-10 18:21:34 -070077#define RECORD_GAIN_MIN 0.0f
78#define RECORD_GAIN_MAX 1.0f
79#define RECORD_VOLUME_CTL_MAX 0x2000
80
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070081#define PROXY_OPEN_RETRY_COUNT 100
82#define PROXY_OPEN_WAIT_TIME 20
83
vivek mehtadae44712015-07-27 14:13:18 -070084#define MIN_CHANNEL_COUNT 1
85#define DEFAULT_CHANNEL_COUNT 2
86
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
88#define MAX_CHANNEL_COUNT 1
89#else
vivek mehtadae44712015-07-27 14:13:18 -070090#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
91#define XSTR(x) STR(x)
92#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070093#endif
Eric Laurent74b55762017-07-09 17:04:53 -070094#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070095
Haynes Mathew George03c40102016-01-29 17:57:48 -080096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Glenn Kasten4f993392014-05-14 07:30:48 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
102#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800103#define MMAP_PERIOD_COUNT_MIN 32
104#define MMAP_PERIOD_COUNT_MAX 512
105#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800106
Andy Hung31aca912014-03-20 17:14:59 -0700107/* This constant enables extended precision handling.
108 * TODO The flag is off until more testing is done.
109 */
110static const bool k_enable_extended_precision = false;
111
Eric Laurentb23d5282013-05-14 15:27:20 -0700112struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700113 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
116 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121};
122
123struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700124 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700125 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
126 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
127 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
128 .format = PCM_FORMAT_S16_LE,
129 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
130 .stop_threshold = INT_MAX,
131 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132};
133
Haynes Mathew George03c40102016-01-29 17:57:48 -0800134static int af_period_multiplier = 4;
135struct pcm_config pcm_config_rt = {
136 .channels = DEFAULT_CHANNEL_COUNT,
137 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
138 .period_size = ULL_PERIOD_SIZE, //1 ms
139 .period_count = 512, //=> buffer size is 512ms
140 .format = PCM_FORMAT_S16_LE,
141 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
142 .stop_threshold = INT_MAX,
143 .silence_threshold = 0,
144 .silence_size = 0,
145 .avail_min = ULL_PERIOD_SIZE, //1 ms
146};
147
Eric Laurentb23d5282013-05-14 15:27:20 -0700148struct pcm_config pcm_config_hdmi_multi = {
149 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
150 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
151 .period_size = HDMI_MULTI_PERIOD_SIZE,
152 .period_count = HDMI_MULTI_PERIOD_COUNT,
153 .format = PCM_FORMAT_S16_LE,
154 .start_threshold = 0,
155 .stop_threshold = INT_MAX,
156 .avail_min = 0,
157};
158
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159struct pcm_config pcm_config_mmap_playback = {
160 .channels = DEFAULT_CHANNEL_COUNT,
161 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
162 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800163 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800164 .format = PCM_FORMAT_S16_LE,
165 .start_threshold = MMAP_PERIOD_SIZE*8,
166 .stop_threshold = INT32_MAX,
167 .silence_threshold = 0,
168 .silence_size = 0,
169 .avail_min = MMAP_PERIOD_SIZE, //1 ms
170};
171
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800172struct pcm_config pcm_config_hifi = {
173 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
174 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
175 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
176 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
177 .format = PCM_FORMAT_S24_3LE,
178 .start_threshold = 0,
179 .stop_threshold = INT_MAX,
180 .avail_min = 0,
181};
182
Eric Laurentb23d5282013-05-14 15:27:20 -0700183struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700184 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
186 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700187 .stop_threshold = INT_MAX,
188 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700189};
190
Haynes Mathew George03c40102016-01-29 17:57:48 -0800191struct pcm_config pcm_config_audio_capture_rt = {
192 .channels = DEFAULT_CHANNEL_COUNT,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = ULL_PERIOD_SIZE,
195 .period_count = 512,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = 0,
198 .stop_threshold = INT_MAX,
199 .silence_threshold = 0,
200 .silence_size = 0,
201 .avail_min = ULL_PERIOD_SIZE, //1 ms
202};
203
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204struct pcm_config pcm_config_mmap_capture = {
205 .channels = DEFAULT_CHANNEL_COUNT,
206 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
207 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800208 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800209 .format = PCM_FORMAT_S16_LE,
210 .start_threshold = 0,
211 .stop_threshold = INT_MAX,
212 .silence_threshold = 0,
213 .silence_size = 0,
214 .avail_min = MMAP_PERIOD_SIZE, //1 ms
215};
216
vivek mehtaa68fea62017-06-08 19:04:02 -0700217struct pcm_config pcm_config_voip = {
218 .channels = 1,
219 .period_count = 2,
220 .format = PCM_FORMAT_S16_LE,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700225#define AFE_PROXY_CHANNEL_COUNT 2
226#define AFE_PROXY_SAMPLING_RATE 48000
227
jiabinad481a72018-07-23 12:03:17 -0700228#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700229#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
230
231struct pcm_config pcm_config_afe_proxy_playback = {
232 .channels = AFE_PROXY_CHANNEL_COUNT,
233 .rate = AFE_PROXY_SAMPLING_RATE,
234 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
236 .format = PCM_FORMAT_S16_LE,
237 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
238 .stop_threshold = INT_MAX,
239 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
240};
241
jiabinad481a72018-07-23 12:03:17 -0700242#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700243#define AFE_PROXY_RECORD_PERIOD_COUNT 4
244
245struct pcm_config pcm_config_afe_proxy_record = {
246 .channels = AFE_PROXY_CHANNEL_COUNT,
247 .rate = AFE_PROXY_SAMPLING_RATE,
248 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
249 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
250 .format = PCM_FORMAT_S16_LE,
251 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700252 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700253 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
254};
255
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700257 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
258 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800259 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700261 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700262 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Eric Laurentb23d5282013-05-14 15:27:20 -0700265 [USECASE_AUDIO_RECORD] = "audio-record",
266 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800267 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700268 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800270 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
271 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700272
Eric Laurentb23d5282013-05-14 15:27:20 -0700273 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700274 [USECASE_VOICE2_CALL] = "voice2-call",
275 [USECASE_VOLTE_CALL] = "volte-call",
276 [USECASE_QCHAT_CALL] = "qchat-call",
277 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800278 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
279 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700281 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
282 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
283
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700284 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
285 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700286
287 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
288 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
289 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
290
vivek mehtaa68fea62017-06-08 19:04:02 -0700291 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
292 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200293
294 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700295
296 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700297};
298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299
300#define STRING_TO_ENUM(string) { #string, string }
301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800302struct string_to_enum {
303 const char *name;
304 uint32_t value;
305};
306
Haynes Mathew George569b7482017-05-08 14:44:27 -0700307static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800308 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700311 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322};
323
Haynes Mathew George5191a852013-09-11 14:19:36 -0700324static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700325static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700326static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700327static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700328//cache last MBDRC cal step level
329static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700330
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800331static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
332static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
333
Haynes Mathew George03c40102016-01-29 17:57:48 -0800334static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
335 int flags __unused)
336{
337 int dir = 0;
338 switch (uc_id) {
339 case USECASE_AUDIO_RECORD_LOW_LATENCY:
340 dir = 1;
341 case USECASE_AUDIO_PLAYBACK_ULL:
342 break;
343 default:
344 return false;
345 }
346
347 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
348 PCM_PLAYBACK : PCM_CAPTURE);
349 if (adev->adm_is_noirq_avail)
350 return adev->adm_is_noirq_avail(adev->adm_data,
351 adev->snd_card, dev_id, dir);
352 return false;
353}
354
355static void register_out_stream(struct stream_out *out)
356{
357 struct audio_device *adev = out->dev;
358 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
359 return;
360
361 if (!adev->adm_register_output_stream)
362 return;
363
364 adev->adm_register_output_stream(adev->adm_data,
365 out->handle,
366 out->flags);
367
368 if (!adev->adm_set_config)
369 return;
370
371 if (out->realtime) {
372 adev->adm_set_config(adev->adm_data,
373 out->handle,
374 out->pcm, &out->config);
375 }
376}
377
378static void register_in_stream(struct stream_in *in)
379{
380 struct audio_device *adev = in->dev;
381 if (!adev->adm_register_input_stream)
382 return;
383
384 adev->adm_register_input_stream(adev->adm_data,
385 in->capture_handle,
386 in->flags);
387
388 if (!adev->adm_set_config)
389 return;
390
391 if (in->realtime) {
392 adev->adm_set_config(adev->adm_data,
393 in->capture_handle,
394 in->pcm,
395 &in->config);
396 }
397}
398
399static void request_out_focus(struct stream_out *out, long ns)
400{
401 struct audio_device *adev = out->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, out->handle);
407 }
408}
409
410static void request_in_focus(struct stream_in *in, long ns)
411{
412 struct audio_device *adev = in->dev;
413
Haynes Mathew George03c40102016-01-29 17:57:48 -0800414 if (adev->adm_request_focus_v2) {
415 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
416 } else if (adev->adm_request_focus) {
417 adev->adm_request_focus(adev->adm_data, in->capture_handle);
418 }
419}
420
421static void release_out_focus(struct stream_out *out, long ns __unused)
422{
423 struct audio_device *adev = out->dev;
424
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, out->handle);
427}
428
429static void release_in_focus(struct stream_in *in, long ns __unused)
430{
431 struct audio_device *adev = in->dev;
432 if (adev->adm_abandon_focus)
433 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
434}
435
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700436static int parse_snd_card_status(struct str_parms * parms, int * card,
437 card_status_t * status)
438{
439 char value[32]={0};
440 char state[32]={0};
441
442 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
443
444 if (ret < 0)
445 return -1;
446
447 // sscanf should be okay as value is of max length 32.
448 // same as sizeof state.
449 if (sscanf(value, "%d,%s", card, state) < 2)
450 return -1;
451
452 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
453 CARD_STATUS_OFFLINE;
454 return 0;
455}
456
vivek mehta40125092017-08-21 18:48:51 -0700457// always call with adev lock held
458void send_gain_dep_calibration_l() {
459 if (last_known_cal_step >= 0)
460 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
461}
462
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463__attribute__ ((visibility ("default")))
464bool audio_hw_send_gain_dep_calibration(int level) {
465 bool ret_val = false;
466 ALOGV("%s: enter ... ", __func__);
467
468 pthread_mutex_lock(&adev_init_lock);
469
470 if (adev != NULL && adev->platform != NULL) {
471 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700472 last_known_cal_step = level;
473 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700474 pthread_mutex_unlock(&adev->lock);
475 } else {
476 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
477 }
478
479 pthread_mutex_unlock(&adev_init_lock);
480
481 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
482 return ret_val;
483}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700484
jasmine cha270b7762018-03-30 15:41:33 +0800485#ifdef MAXXAUDIO_QDSP_ENABLED
486bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
487{
488 bool ret = false;
489 ALOGV("%s: enter ...", __func__);
490
491 pthread_mutex_lock(&adev_init_lock);
492
493 if (adev != NULL && adev->platform != NULL) {
494 pthread_mutex_lock(&adev->lock);
495 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
496 pthread_mutex_unlock(&adev->lock);
497 }
498
499 pthread_mutex_unlock(&adev_init_lock);
500
501 ALOGV("%s: exit with ret %d", __func__, ret);
502 return ret;
503}
504#else
505#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
506#endif
507
vivek mehtaa8d7c922016-05-25 14:40:44 -0700508__attribute__ ((visibility ("default")))
509int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
510 int table_size) {
511 int ret_val = 0;
512 ALOGV("%s: enter ... ", __func__);
513
514 pthread_mutex_lock(&adev_init_lock);
515 if (adev == NULL) {
516 ALOGW("%s: adev is NULL .... ", __func__);
517 goto done;
518 }
519
520 pthread_mutex_lock(&adev->lock);
521 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
522 pthread_mutex_unlock(&adev->lock);
523done:
524 pthread_mutex_unlock(&adev_init_lock);
525 ALOGV("%s: exit ... ", __func__);
526 return ret_val;
527}
528
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700529static bool is_supported_format(audio_format_t format)
530{
Eric Laurent8251ac82014-07-23 11:00:25 -0700531 switch (format) {
532 case AUDIO_FORMAT_MP3:
533 case AUDIO_FORMAT_AAC_LC:
534 case AUDIO_FORMAT_AAC_HE_V1:
535 case AUDIO_FORMAT_AAC_HE_V2:
536 return true;
537 default:
538 break;
539 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700540 return false;
541}
542
juyuchenbe5c67e2018-08-29 17:19:20 +0800543static bool is_supported_24bits_audiosource(audio_source_t source)
544{
545 switch (source) {
546 case AUDIO_SOURCE_UNPROCESSED:
547#ifdef ENABLED_24BITS_CAMCORDER
548 case AUDIO_SOURCE_CAMCORDER:
549#endif
550 return true;
551 default:
552 break;
553 }
554 return false;
555}
556
Haynes Mathew George03c40102016-01-29 17:57:48 -0800557static inline bool is_mmap_usecase(audio_usecase_t uc_id)
558{
559 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
560 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
561}
562
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700563static int get_snd_codec_id(audio_format_t format)
564{
565 int id = 0;
566
Eric Laurent8251ac82014-07-23 11:00:25 -0700567 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 case AUDIO_FORMAT_MP3:
569 id = SND_AUDIOCODEC_MP3;
570 break;
571 case AUDIO_FORMAT_AAC:
572 id = SND_AUDIOCODEC_AAC;
573 break;
574 default:
575 ALOGE("%s: Unsupported audio format", __func__);
576 }
577
578 return id;
579}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800580
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800581static int audio_ssr_status(struct audio_device *adev)
582{
583 int ret = 0;
584 struct mixer_ctl *ctl;
585 const char *mixer_ctl_name = "Audio SSR Status";
586
587 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
588 ret = mixer_ctl_get_value(ctl, 0);
589 ALOGD("%s: value: %d", __func__, ret);
590 return ret;
591}
592
vivek mehta4a824772017-06-08 19:05:49 -0700593static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
594{
595 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
596}
597
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800598static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
599{
600 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
601 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
602 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
605 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
606
607}
608
609static bool is_a2dp_device(snd_device_t out_snd_device)
610{
611 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
612}
613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800614int enable_audio_route(struct audio_device *adev,
615 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800616{
yixuanjiang509f0a72018-09-06 18:37:23 +0800617 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700618 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800619
620 if (usecase == NULL)
621 return -EINVAL;
622
623 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
624
yixuanjiang509f0a72018-09-06 18:37:23 +0800625 if (usecase->type == PCM_CAPTURE)
626 snd_device = usecase->in_snd_device;
627 else
628 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530629 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800630 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700631
632 // we shouldn't truncate mixer_path
633 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
634 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
635 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800636 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700637
yixuanjiang509f0a72018-09-06 18:37:23 +0800638 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700639 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700640 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642 ALOGV("%s: exit", __func__);
643 return 0;
644}
645
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800646int disable_audio_route(struct audio_device *adev,
647 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800648{
yixuanjiang509f0a72018-09-06 18:37:23 +0800649 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700650 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800651
652 if (usecase == NULL)
653 return -EINVAL;
654
655 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800656 if (usecase->type == PCM_CAPTURE)
657 snd_device = usecase->in_snd_device;
658 else
659 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700660
661 // we shouldn't truncate mixer_path
662 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
663 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
664 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800665 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700666 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700667
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700668 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000669 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 ALOGV("%s: exit", __func__);
672 return 0;
673}
674
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800675int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700676 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700678 int i, num_devices = 0;
679 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800680 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800681 if (snd_device < SND_DEVICE_MIN ||
682 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800683 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800684 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800685 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700686
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700687 platform_send_audio_calibration(adev->platform, snd_device);
688
vivek mehtade4849c2016-03-03 17:23:38 -0800689 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700690 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700691 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800692 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 }
694
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700695 /* due to the possibility of calibration overwrite between listen
696 and audio, notify sound trigger hal before audio calibration is sent */
697 audio_extn_sound_trigger_update_device_status(snd_device,
698 ST_EVENT_SND_DEVICE_BUSY);
699
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700700 if (audio_extn_spkr_prot_is_enabled())
701 audio_extn_spkr_prot_calib_cancel(adev);
702
zhaoyang yin4211fad2015-06-04 21:13:25 +0800703 audio_extn_dsm_feedback_enable(adev, snd_device, true);
704
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700705 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800706 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800707 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
709 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700710 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800711 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700712 }
713 if (audio_extn_spkr_prot_start_processing(snd_device)) {
714 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800715 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700717 } else if (platform_can_split_snd_device(snd_device,
718 &num_devices,
719 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700720 for (i = 0; i < num_devices; i++) {
721 enable_snd_device(adev, new_snd_devices[i]);
722 }
vivek mehtab6506412015-08-07 16:55:17 -0700723 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700724 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800725 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
726 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
727 ALOGE(" %s: Invalid sound device returned", __func__);
728 goto on_error;
729 }
Ed Tam70b5c142016-03-21 19:14:29 -0700730
Eric Laurent2e140aa2016-06-30 17:14:46 -0700731 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700732
733 if (is_a2dp_device(snd_device) &&
734 (audio_extn_a2dp_start_playback() < 0)) {
735 ALOGE("%s: failed to configure A2DP control path", __func__);
736 goto on_error;
737 }
738
vivek mehtade4849c2016-03-03 17:23:38 -0800739 audio_route_apply_and_update_path(adev->audio_route, device_name);
740 }
741on_success:
742 adev->snd_dev_ref_cnt[snd_device]++;
743 ret_val = 0;
744on_error:
745 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746}
747
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800748int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700749 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700751 int i, num_devices = 0;
752 snd_device_t new_snd_devices[2];
753
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800754 if (snd_device < SND_DEVICE_MIN ||
755 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800756 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 return -EINVAL;
758 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
760 ALOGE("%s: device ref cnt is already 0", __func__);
761 return -EINVAL;
762 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800763 audio_extn_tfa_98xx_disable_speaker(snd_device);
764
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700765 adev->snd_dev_ref_cnt[snd_device]--;
766 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800767 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800768
769 if (is_a2dp_device(snd_device))
770 audio_extn_a2dp_stop_playback();
771
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700772 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800773 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700774 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700775 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
776 audio_extn_spkr_prot_is_enabled()) {
777 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700778
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700779 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
780 // and does not use speaker swap. As this code causes a problem with device enable ref
781 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700782 // when speaker device is disabled, reset swap.
783 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700784 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700785
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786 } else if (platform_can_split_snd_device(snd_device,
787 &num_devices,
788 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700789 for (i = 0; i < num_devices; i++) {
790 disable_snd_device(adev, new_snd_devices[i]);
791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700793 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800794 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
795 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE(" %s: Invalid sound device returned", __func__);
797 return -EINVAL;
798 }
799
Eric Laurent2e140aa2016-06-30 17:14:46 -0700800 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800801 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700802 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700803 audio_extn_sound_trigger_update_device_status(snd_device,
804 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 }
vivek mehtab6506412015-08-07 16:55:17 -0700806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800807 return 0;
808}
809
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800810#ifdef DYNAMIC_ECNS_ENABLED
811static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
812 struct stream_in *in,
813 struct audio_effect_config effect_config,
814 unsigned int param_value)
815{
816 char mixer_ctl_name[] = "Audio Effect";
817 long set_values[6];
818
819 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
820 if (!ctl) {
821 ALOGE("%s: Could not get mixer ctl - %s",
822 __func__, mixer_ctl_name);
823 return -EINVAL;
824 }
825
826 set_values[0] = 1; //0:Rx 1:Tx
827 set_values[1] = in->app_type_cfg.app_type;
828 set_values[2] = (long)effect_config.module_id;
829 set_values[3] = (long)effect_config.instance_id;
830 set_values[4] = (long)effect_config.param_id;
831 set_values[5] = param_value;
832
833 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
834
835 return 0;
836
837}
838
839static int update_effect_param_ecns(struct audio_usecase *usecase,
840 unsigned int module_id, int effect_type,
841 unsigned int *param_value)
842{
843 int ret = 0;
844 struct audio_effect_config other_effect_config;
845 struct stream_in *in = NULL;
846
847 if (!usecase)
848 return -EINVAL;
849
850 in = usecase->stream.in;
851
852 /* Get the effect config data of the other effect */
853 ret = platform_get_effect_config_data(usecase->in_snd_device,
854 &other_effect_config,
855 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
856 if (ret < 0) {
857 ALOGE("%s Failed to get effect params %d", __func__, ret);
858 return ret;
859 }
860
861 if (module_id == other_effect_config.module_id) {
862 //Same module id for AEC/NS. Values need to be combined
863 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
864 ((effect_type == EFFECT_NS) && (in->enable_aec)))
865 *param_value |= other_effect_config.param_value;
866 }
867
868 return ret;
869}
870
871static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
872 int effect_type, bool enable)
873{
874 struct audio_effect_config effect_config;
875 struct audio_usecase *usecase = NULL;
876 int ret = 0;
877 unsigned int param_value = 0;
878
879 if (!in) {
880 ALOGE("%s: Invalid input stream", __func__);
881 return -EINVAL;
882 }
883
884 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
885
886 usecase = get_usecase_from_list(adev, in->usecase);
887
888 ret = platform_get_effect_config_data(usecase->in_snd_device,
889 &effect_config, effect_type);
890 if (ret < 0) {
891 ALOGE("%s Failed to get module id %d", __func__, ret);
892 return ret;
893 }
894 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
895 __func__, effect_config.module_id, in->app_type_cfg.app_type,
896 usecase->id, usecase->in_snd_device);
897
898 if (enable)
899 param_value = effect_config.param_value;
900
901 /*Special handling for AEC & NS effects Param values need to be
902 updated if module ids are same*/
903
904 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
905 ret = update_effect_param_ecns(usecase, effect_config.module_id,
906 effect_type, &param_value);
907 if (ret < 0)
908 return ret;
909 }
910
911 ret = send_effect_enable_disable_mixer_ctl(adev, in,
912 effect_config, param_value);
913
914 return ret;
915}
916
917static int check_and_enable_effect(struct audio_device *adev)
918{
919 int ret = 0;
920
921 struct listnode *node;
922 struct stream_in *in = NULL;
923
924 list_for_each(node, &adev->usecase_list)
925 {
926 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
927 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
928 in = usecase->stream.in;
929
930 if (in->standby)
931 continue;
932
933 if (in->enable_aec) {
934 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
935 }
936
937 if (in->enable_ns &&
938 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
939 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
940 }
941 }
942 }
943
944 return ret;
945}
946#else
947#define enable_disable_effect(w, x, y, z) -ENOSYS
948#define check_and_enable_effect(x) -ENOSYS
949#endif
950
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700951/*
952 legend:
953 uc - existing usecase
954 new_uc - new usecase
955 d1, d11, d2 - SND_DEVICE enums
956 a1, a2 - corresponding ANDROID device enums
957 B, B1, B2 - backend strings
958
959case 1
960 uc->dev d1 (a1) B1
961 new_uc->dev d1 (a1), d2 (a2) B1, B2
962
963 resolution: disable and enable uc->dev on d1
964
965case 2
966 uc->dev d1 (a1) B1
967 new_uc->dev d11 (a1) B1
968
969 resolution: need to switch uc since d1 and d11 are related
970 (e.g. speaker and voice-speaker)
971 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
972
973case 3
974 uc->dev d1 (a1) B1
975 new_uc->dev d2 (a2) B2
976
977 resolution: no need to switch uc
978
979case 4
980 uc->dev d1 (a1) B
981 new_uc->dev d2 (a2) B
982
983 resolution: disable enable uc-dev on d2 since backends match
984 we cannot enable two streams on two different devices if they
985 share the same backend. e.g. if offload is on speaker device using
986 QUAD_MI2S backend and a low-latency stream is started on voice-handset
987 using the same backend, offload must also be switched to voice-handset.
988
989case 5
990 uc->dev d1 (a1) B
991 new_uc->dev d1 (a1), d2 (a2) B
992
993 resolution: disable enable uc-dev on d2 since backends match
994 we cannot enable two streams on two different devices if they
995 share the same backend.
996
997case 6
998 uc->dev d1 a1 B1
999 new_uc->dev d2 a1 B2
1000
1001 resolution: no need to switch
1002
1003case 7
1004
1005 uc->dev d1 (a1), d2 (a2) B1, B2
1006 new_uc->dev d1 B1
1007
1008 resolution: no need to switch
1009
1010*/
1011static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1012 struct audio_usecase *new_uc,
1013 snd_device_t new_snd_device)
1014{
1015 audio_devices_t a1 = uc->stream.out->devices;
1016 audio_devices_t a2 = new_uc->stream.out->devices;
1017
1018 snd_device_t d1 = uc->out_snd_device;
1019 snd_device_t d2 = new_snd_device;
1020
1021 // Treat as a special case when a1 and a2 are not disjoint
1022 if ((a1 != a2) && (a1 & a2)) {
1023 snd_device_t d3[2];
1024 int num_devices = 0;
1025 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1026 &num_devices,
1027 d3);
1028 if (ret < 0) {
1029 if (ret != -ENOSYS) {
1030 ALOGW("%s failed to split snd_device %d",
1031 __func__,
1032 popcount(a1) > 1 ? d1 : d2);
1033 }
1034 goto end;
1035 }
1036
1037 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1038 // But if it does happen, we need to give priority to d2 if
1039 // the combo devices active on the existing usecase share a backend.
1040 // This is because we cannot have a usecase active on a combo device
1041 // and a new usecase requests one device in this combo pair.
1042 if (platform_check_backends_match(d3[0], d3[1])) {
1043 return d2; // case 5
1044 } else {
1045 return d1; // case 1
1046 }
1047 } else {
1048 if (platform_check_backends_match(d1, d2)) {
1049 return d2; // case 2, 4
1050 } else {
1051 return d1; // case 6, 3
1052 }
1053 }
1054
1055end:
1056 return d2; // return whatever was calculated before.
1057}
1058
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001059static void check_and_route_playback_usecases(struct audio_device *adev,
1060 struct audio_usecase *uc_info,
1061 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062{
1063 struct listnode *node;
1064 struct audio_usecase *usecase;
1065 bool switch_device[AUDIO_USECASE_MAX];
1066 int i, num_uc_to_switch = 0;
1067
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001068 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1069 uc_info,
1070 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001071
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001072 /* For a2dp device reconfigure all active sessions
1073 * with new AFE encoder format based on a2dp state
1074 */
1075 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001076 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1077 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001078 audio_extn_a2dp_is_force_device_switch()) {
1079 force_routing = true;
1080 }
1081
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001082 /*
1083 * This function is to make sure that all the usecases that are active on
1084 * the hardware codec backend are always routed to any one device that is
1085 * handled by the hardware codec.
1086 * For example, if low-latency and deep-buffer usecases are currently active
1087 * on speaker and out_set_parameters(headset) is received on low-latency
1088 * output, then we have to make sure deep-buffer is also switched to headset,
1089 * because of the limitation that both the devices cannot be enabled
1090 * at the same time as they share the same backend.
1091 */
1092 /* Disable all the usecases on the shared backend other than the
1093 specified usecase */
1094 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1095 switch_device[i] = false;
1096
1097 list_for_each(node, &adev->usecase_list) {
1098 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001099 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1100 continue;
1101
1102 if (force_routing ||
1103 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001104 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1105 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001106 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1108 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001109 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001110 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 switch_device[usecase->id] = true;
1112 num_uc_to_switch++;
1113 }
1114 }
1115
1116 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001117 list_for_each(node, &adev->usecase_list) {
1118 usecase = node_to_item(node, struct audio_usecase, list);
1119 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001120 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001121 }
1122 }
1123
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001124 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001125 list_for_each(node, &adev->usecase_list) {
1126 usecase = node_to_item(node, struct audio_usecase, list);
1127 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001128 d_device = derive_playback_snd_device(usecase, uc_info,
1129 snd_device);
1130 enable_snd_device(adev, d_device);
1131 /* Update the out_snd_device before enabling the audio route */
1132 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 }
1134 }
1135
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 /* Re-route all the usecases on the shared backend other than the
1137 specified usecase to new snd devices */
1138 list_for_each(node, &adev->usecase_list) {
1139 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001141 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 }
1143 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 }
1145}
1146
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001147static void check_and_route_capture_usecases(struct audio_device *adev,
1148 struct audio_usecase *uc_info,
1149 snd_device_t snd_device)
1150{
1151 struct listnode *node;
1152 struct audio_usecase *usecase;
1153 bool switch_device[AUDIO_USECASE_MAX];
1154 int i, num_uc_to_switch = 0;
1155
vivek mehta4ed66e62016-04-15 23:33:34 -07001156 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1157
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001158 /*
1159 * This function is to make sure that all the active capture usecases
1160 * are always routed to the same input sound device.
1161 * For example, if audio-record and voice-call usecases are currently
1162 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1163 * is received for voice call then we have to make sure that audio-record
1164 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1165 * because of the limitation that two devices cannot be enabled
1166 * at the same time if they share the same backend.
1167 */
1168 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1169 switch_device[i] = false;
1170
1171 list_for_each(node, &adev->usecase_list) {
1172 usecase = node_to_item(node, struct audio_usecase, list);
1173 if (usecase->type != PCM_PLAYBACK &&
1174 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001175 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001176 ((uc_info->type == VOICE_CALL &&
1177 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1178 platform_check_backends_match(snd_device,\
1179 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001180 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001181 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1182 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001183 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001184 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 switch_device[usecase->id] = true;
1186 num_uc_to_switch++;
1187 }
1188 }
1189
1190 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001191 list_for_each(node, &adev->usecase_list) {
1192 usecase = node_to_item(node, struct audio_usecase, list);
1193 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001194 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001195 }
1196 }
1197
1198 list_for_each(node, &adev->usecase_list) {
1199 usecase = node_to_item(node, struct audio_usecase, list);
1200 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001201 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001202 }
1203 }
1204
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001205 /* Re-route all the usecases on the shared backend other than the
1206 specified usecase to new snd devices */
1207 list_for_each(node, &adev->usecase_list) {
1208 usecase = node_to_item(node, struct audio_usecase, list);
1209 /* Update the in_snd_device only before enabling the audio route */
1210 if (switch_device[usecase->id] ) {
1211 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001212 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 }
1214 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215 }
1216}
1217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001219static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001220{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001221 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001222 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223
1224 switch (channels) {
1225 /*
1226 * Do not handle stereo output in Multi-channel cases
1227 * Stereo case is handled in normal playback path
1228 */
1229 case 6:
1230 ALOGV("%s: HDMI supports 5.1", __func__);
1231 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1232 break;
1233 case 8:
1234 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1235 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1236 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1237 break;
1238 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001239 ALOGE("HDMI does not support multi channel playback");
1240 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 break;
1242 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001243 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244}
1245
Andy Hung18859412017-08-09 11:47:21 -07001246static ssize_t read_usb_sup_sample_rates(bool is_playback,
1247 uint32_t *supported_sample_rates,
1248 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001249{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001250 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1251 supported_sample_rates,
1252 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001253#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001254 for (ssize_t i=0; i<count; i++) {
1255 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1256 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001257 }
1258#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001259 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001260}
1261
Haynes Mathew George569b7482017-05-08 14:44:27 -07001262static int read_usb_sup_channel_masks(bool is_playback,
1263 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001264 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001265{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001266 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001267 int channel_count;
1268 uint32_t num_masks = 0;
1269 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1270 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001271 }
Eric Laurent74b55762017-07-09 17:04:53 -07001272 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001273 // start from 2 channels as framework currently doesn't support mono.
1274 // TODO: consider only supporting channel index masks beyond stereo here.
1275 for (channel_count = FCC_2;
1276 channel_count <= channels && num_masks < max_masks;
1277 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001278 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1279 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001280 for (channel_count = FCC_2;
1281 channel_count <= channels && num_masks < max_masks;
1282 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001283 supported_channel_masks[num_masks++] =
1284 audio_channel_mask_for_index_assignment_from_count(channel_count);
1285 }
1286 } else {
1287 // For capture we report all supported channel masks from 1 channel up.
1288 channel_count = MIN_CHANNEL_COUNT;
1289 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1290 // indexed mask
1291 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001292 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001293 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001294 supported_channel_masks[num_masks++] = mask;
1295 const audio_channel_mask_t index_mask =
1296 audio_channel_mask_for_index_assignment_from_count(channel_count);
1297 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1298 supported_channel_masks[num_masks++] = index_mask;
1299 }
Eric Laurent74b55762017-07-09 17:04:53 -07001300 }
1301 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001302#ifdef NDEBUG
1303 for (size_t i = 0; i < num_masks; ++i) {
1304 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1305 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1306 }
1307#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001308 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001309}
1310
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001311static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001312 audio_format_t *supported_formats,
1313 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001314{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001315 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001316 switch (bitwidth) {
1317 case 24:
1318 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001319 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001320 break;
1321 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001322 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001323 break;
1324 case 16:
1325 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001326 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001327 break;
1328 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001329 ALOGV("%s: %s supported format %d", __func__,
1330 is_playback ? "P" : "C", bitwidth);
1331 return 1;
1332}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001333
Haynes Mathew George569b7482017-05-08 14:44:27 -07001334static int read_usb_sup_params_and_compare(bool is_playback,
1335 audio_format_t *format,
1336 audio_format_t *supported_formats,
1337 uint32_t max_formats,
1338 audio_channel_mask_t *mask,
1339 audio_channel_mask_t *supported_channel_masks,
1340 uint32_t max_masks,
1341 uint32_t *rate,
1342 uint32_t *supported_sample_rates,
1343 uint32_t max_rates) {
1344 int ret = 0;
1345 int num_formats;
1346 int num_masks;
1347 int num_rates;
1348 int i;
1349
1350 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1351 max_formats);
1352 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1353 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001354
Haynes Mathew George569b7482017-05-08 14:44:27 -07001355 num_rates = read_usb_sup_sample_rates(is_playback,
1356 supported_sample_rates, max_rates);
1357
1358#define LUT(table, len, what, dflt) \
1359 for (i=0; i<len && (table[i] != what); i++); \
1360 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1361
1362 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1363 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1364 LUT(supported_sample_rates, num_rates, *rate, 0);
1365
1366#undef LUT
1367 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001368}
1369
Andy Hungd9653bd2017-08-01 19:31:39 -07001370static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1371{
1372 // Check if usb is ready.
1373 // The usb device may have been removed quickly after insertion and hence
1374 // no longer available. This will show up as empty channel masks, or rates.
1375
1376 pthread_mutex_lock(&adev->lock);
1377 uint32_t supported_sample_rate;
1378
1379 // we consider usb ready if we can fetch at least one sample rate.
1380 const bool ready = read_usb_sup_sample_rates(
1381 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1382 pthread_mutex_unlock(&adev->lock);
1383 return ready;
1384}
1385
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001386static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1387{
1388 struct audio_usecase *usecase;
1389 struct listnode *node;
1390
1391 list_for_each(node, &adev->usecase_list) {
1392 usecase = node_to_item(node, struct audio_usecase, list);
1393 if (usecase->type == VOICE_CALL) {
1394 ALOGV("%s: usecase id %d", __func__, usecase->id);
1395 return usecase->id;
1396 }
1397 }
1398 return USECASE_INVALID;
1399}
1400
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001401struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1402 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001403{
1404 struct audio_usecase *usecase;
1405 struct listnode *node;
1406
1407 list_for_each(node, &adev->usecase_list) {
1408 usecase = node_to_item(node, struct audio_usecase, list);
1409 if (usecase->id == uc_id)
1410 return usecase;
1411 }
1412 return NULL;
1413}
1414
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001415static bool force_device_switch(struct audio_usecase *usecase)
1416{
1417 if (usecase->stream.out == NULL) {
1418 ALOGE("%s: stream.out is NULL", __func__);
1419 return false;
1420 }
1421
1422 // Force all A2DP output devices to reconfigure for proper AFE encode format
1423 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1424 // in suspended state, hence try to trigger a retry when we again get a routing request.
1425 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1426 audio_extn_a2dp_is_force_device_switch()) {
1427 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1428 return true;
1429 }
1430
1431 return false;
1432}
1433
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001434struct stream_in *adev_get_active_input(const struct audio_device *adev)
1435{
1436 struct listnode *node;
1437 struct stream_in *last_active_in = NULL;
1438
1439 /* Get last added active input.
1440 * TODO: We may use a priority mechanism to pick highest priority active source */
1441 list_for_each(node, &adev->usecase_list)
1442 {
1443 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1444 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1445 last_active_in = usecase->stream.in;
1446 }
1447 }
1448
1449 return last_active_in;
1450}
1451
1452struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1453{
1454 struct listnode *node;
1455
1456 /* First check active inputs with voice communication source and then
1457 * any input if audio mode is in communication */
1458 list_for_each(node, &adev->usecase_list)
1459 {
1460 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1461 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1462 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1463 return usecase->stream.in;
1464 }
1465 }
1466 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1467 return adev_get_active_input(adev);
1468 }
1469 return NULL;
1470}
1471
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001472int select_devices(struct audio_device *adev,
1473 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001474{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001475 snd_device_t out_snd_device = SND_DEVICE_NONE;
1476 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001477 struct audio_usecase *usecase = NULL;
1478 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001479 struct audio_usecase *hfp_usecase = NULL;
1480 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001481 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001482 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001483 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1484 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 usecase = get_usecase_from_list(adev, uc_id);
1487 if (usecase == NULL) {
1488 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1489 return -EINVAL;
1490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001492 if ((usecase->type == VOICE_CALL) ||
1493 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001494 out_snd_device = platform_get_output_snd_device(adev->platform,
1495 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001496 in_snd_device = platform_get_input_snd_device(adev->platform,
1497 NULL,
1498 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001499 usecase->devices = usecase->stream.out->devices;
1500 } else {
1501 /*
1502 * If the voice call is active, use the sound devices of voice call usecase
1503 * so that it would not result any device switch. All the usecases will
1504 * be switched to new device when select_devices() is called for voice call
1505 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001506 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001508 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001509 vc_usecase = get_usecase_from_list(adev,
1510 get_voice_usecase_id_from_list(adev));
1511 if ((vc_usecase != NULL) &&
1512 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001513 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1514 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 in_snd_device = vc_usecase->in_snd_device;
1516 out_snd_device = vc_usecase->out_snd_device;
1517 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001518 } else if (audio_extn_hfp_is_active(adev)) {
1519 hfp_ucid = audio_extn_hfp_get_usecase();
1520 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1521 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1522 in_snd_device = hfp_usecase->in_snd_device;
1523 out_snd_device = hfp_usecase->out_snd_device;
1524 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 }
1526 if (usecase->type == PCM_PLAYBACK) {
1527 usecase->devices = usecase->stream.out->devices;
1528 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001529 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001530 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001531 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001532
Eric Laurentb23d5282013-05-14 15:27:20 -07001533 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001534 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001535
1536 if (voip_usecase)
1537 voip_out = voip_usecase->stream.out;
1538
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001539 if (usecase->stream.out == voip_out && voip_in != NULL) {
1540 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001541 }
1542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001543 } else if (usecase->type == PCM_CAPTURE) {
1544 usecase->devices = usecase->stream.in->device;
1545 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001546 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001547 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001548 struct stream_in *voip_in = get_voice_communication_input(adev);
1549
1550 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001551
1552 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1553 USECASE_AUDIO_PLAYBACK_VOIP);
1554
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001555 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001556 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1557 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001558 } else if (voip_usecase) {
1559 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001560 } else if (adev->primary_output &&
1561 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001562 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001563 } else {
1564 /* forcing speaker o/p device to get matching i/p pair
1565 in case o/p is not routed from same primary HAL */
1566 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001567 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001568 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001569 in_snd_device = platform_get_input_snd_device(adev->platform,
1570 usecase->stream.in,
1571 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001572 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 }
1574 }
1575
1576 if (out_snd_device == usecase->out_snd_device &&
1577 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001578 if (!force_device_switch(usecase))
1579 return 0;
1580 }
1581
1582 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1583 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1584 return 0;
1585 }
1586
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001587 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1588 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001589 (!audio_extn_a2dp_is_ready())) {
1590 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001591 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1592 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1593 else
1594 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001595 }
1596
juyuchen66c4ecf2018-08-06 15:39:34 +08001597 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1598 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1599 }
1600
Eric Laurent2bafff12016-03-17 12:17:23 -07001601 if (out_snd_device != SND_DEVICE_NONE &&
1602 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1603 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1604 __func__,
1605 use_case_table[uc_id],
1606 adev->last_logged_snd_device[uc_id][0],
1607 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1608 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1609 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1610 -1,
1611 out_snd_device,
1612 platform_get_snd_device_name(out_snd_device),
1613 platform_get_snd_device_acdb_id(out_snd_device));
1614 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1615 }
1616 if (in_snd_device != SND_DEVICE_NONE &&
1617 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1618 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1619 __func__,
1620 use_case_table[uc_id],
1621 adev->last_logged_snd_device[uc_id][1],
1622 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1623 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1624 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1625 -1,
1626 in_snd_device,
1627 platform_get_snd_device_name(in_snd_device),
1628 platform_get_snd_device_acdb_id(in_snd_device));
1629 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1630 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632 /*
1633 * Limitation: While in call, to do a device switch we need to disable
1634 * and enable both RX and TX devices though one of them is same as current
1635 * device.
1636 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001637 if ((usecase->type == VOICE_CALL) &&
1638 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1639 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001640 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001641 /* Disable sidetone only if voice call already exists */
1642 if (voice_is_call_state_active(adev))
1643 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001644 }
1645
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 /* Disable current sound devices */
1647 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001648 disable_audio_route(adev, usecase);
1649 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 }
1651
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001653 disable_audio_route(adev, usecase);
1654 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 }
1656
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001657 /* Applicable only on the targets that has external modem.
1658 * New device information should be sent to modem before enabling
1659 * the devices to reduce in-call device switch time.
1660 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001661 if ((usecase->type == VOICE_CALL) &&
1662 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1663 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001664 status = platform_switch_voice_call_enable_device_config(adev->platform,
1665 out_snd_device,
1666 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001667 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001668
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001669 /* Enable new sound devices */
1670 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001671 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001672 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1673 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001674 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001675 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 }
1677
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001678 if (in_snd_device != SND_DEVICE_NONE) {
1679 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001680 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001681 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001682
Eric Laurentb23d5282013-05-14 15:27:20 -07001683 if (usecase->type == VOICE_CALL)
1684 status = platform_switch_voice_call_device_post(adev->platform,
1685 out_snd_device,
1686 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001687
sangwoo170731f2013-06-08 15:36:36 +09001688 usecase->in_snd_device = in_snd_device;
1689 usecase->out_snd_device = out_snd_device;
1690
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001691 audio_extn_tfa_98xx_set_mode();
1692
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001693 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001694
Jasmine Cha70771b62018-05-15 15:02:43 +08001695 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001696
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001697 /* If input stream is already running the effect needs to be
1698 applied on the new input device that's being enabled here. */
1699 if (in_snd_device != SND_DEVICE_NONE)
1700 check_and_enable_effect(adev);
1701
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001702 /* Applicable only on the targets that has external modem.
1703 * Enable device command should be sent to modem only after
1704 * enabling voice call mixer controls
1705 */
vivek mehta765eb642015-08-07 19:46:06 -07001706 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001707 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1708 out_snd_device,
1709 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001710 /* Enable sidetone only if voice call already exists */
1711 if (voice_is_call_state_active(adev))
1712 voice_set_sidetone(adev, out_snd_device, true);
1713 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001714
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001715 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001716 struct stream_out *voip_out = voip_usecase->stream.out;
1717 audio_extn_utils_send_app_type_gain(adev,
1718 voip_out->app_type_cfg.app_type,
1719 &voip_out->app_type_cfg.gain[0]);
1720 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721 return status;
1722}
1723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001724static int stop_input_stream(struct stream_in *in)
1725{
1726 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 struct audio_usecase *uc_info;
1728 struct audio_device *adev = in->dev;
1729
Eric Laurent994a6932013-07-17 11:51:42 -07001730 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001731 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733 uc_info = get_usecase_from_list(adev, in->usecase);
1734 if (uc_info == NULL) {
1735 ALOGE("%s: Could not find the usecase (%d) in the list",
1736 __func__, in->usecase);
1737 return -EINVAL;
1738 }
1739
vivek mehta781065c2017-04-04 12:55:01 -07001740 /* Close in-call recording streams */
1741 voice_check_and_stop_incall_rec_usecase(adev, in);
1742
Eric Laurent150dbfe2013-02-27 14:31:02 -08001743 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001744 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001745
1746 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001747 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001749 list_remove(&uc_info->list);
1750 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001751
Eric Laurent994a6932013-07-17 11:51:42 -07001752 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 return ret;
1754}
1755
1756int start_input_stream(struct stream_in *in)
1757{
1758 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001759 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 struct audio_usecase *uc_info;
1761 struct audio_device *adev = in->dev;
1762
Eric Laurent994a6932013-07-17 11:51:42 -07001763 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001764
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001765 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1766 return -EIO;
1767
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001768 if (in->card_status == CARD_STATUS_OFFLINE ||
1769 adev->card_status == CARD_STATUS_OFFLINE) {
1770 ALOGW("in->card_status or adev->card_status offline, try again");
1771 ret = -EAGAIN;
1772 goto error_config;
1773 }
1774
vivek mehta781065c2017-04-04 12:55:01 -07001775 /* Check if source matches incall recording usecase criteria */
1776 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1777 if (ret)
1778 goto error_config;
1779 else
1780 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1781
Eric Laurentb23d5282013-05-14 15:27:20 -07001782 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 if (in->pcm_device_id < 0) {
1784 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1785 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001786 ret = -EINVAL;
1787 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1791 uc_info->id = in->usecase;
1792 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001793 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001794 uc_info->devices = in->device;
1795 uc_info->in_snd_device = SND_DEVICE_NONE;
1796 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001798 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001799
Wei Wangf4837d52017-11-21 14:51:20 -08001800 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001801 audio_extn_perf_lock_acquire();
1802
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804
Eric Laurent0e46adf2016-12-16 12:49:24 -08001805 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001806 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001807 ALOGE("%s: pcm stream not ready", __func__);
1808 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001809 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001810 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001811 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001812 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1813 goto error_open;
1814 }
1815 } else {
1816 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1817 unsigned int pcm_open_retry_count = 0;
1818
1819 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1820 flags |= PCM_MMAP | PCM_NOIRQ;
1821 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1822 } else if (in->realtime) {
1823 flags |= PCM_MMAP | PCM_NOIRQ;
1824 }
1825
1826 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1827 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1828
1829 while (1) {
1830 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1831 flags, &in->config);
1832 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1833 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1834 if (in->pcm != NULL) {
1835 pcm_close(in->pcm);
1836 in->pcm = NULL;
1837 }
1838 if (pcm_open_retry_count-- == 0) {
1839 ret = -EIO;
1840 goto error_open;
1841 }
1842 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1843 continue;
1844 }
1845 break;
1846 }
1847
1848 ALOGV("%s: pcm_prepare", __func__);
1849 ret = pcm_prepare(in->pcm);
1850 if (ret < 0) {
1851 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001852 pcm_close(in->pcm);
1853 in->pcm = NULL;
1854 goto error_open;
1855 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001856 if (in->realtime) {
1857 ret = pcm_start(in->pcm);
1858 if (ret < 0) {
1859 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1860 pcm_close(in->pcm);
1861 in->pcm = NULL;
1862 goto error_open;
1863 }
1864 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001865 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001866 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001867 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001868 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001869 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001870 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001871
Eric Laurent0e46adf2016-12-16 12:49:24 -08001872 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001873
1874error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001876 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001877 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001878
1879error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001880 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001881 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882}
1883
Eric Laurenta1478072015-09-21 17:21:52 -07001884void lock_input_stream(struct stream_in *in)
1885{
1886 pthread_mutex_lock(&in->pre_lock);
1887 pthread_mutex_lock(&in->lock);
1888 pthread_mutex_unlock(&in->pre_lock);
1889}
1890
1891void lock_output_stream(struct stream_out *out)
1892{
1893 pthread_mutex_lock(&out->pre_lock);
1894 pthread_mutex_lock(&out->lock);
1895 pthread_mutex_unlock(&out->pre_lock);
1896}
1897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001898/* must be called with out->lock locked */
1899static int send_offload_cmd_l(struct stream_out* out, int command)
1900{
1901 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1902
1903 ALOGVV("%s %d", __func__, command);
1904
1905 cmd->cmd = command;
1906 list_add_tail(&out->offload_cmd_list, &cmd->node);
1907 pthread_cond_signal(&out->offload_cond);
1908 return 0;
1909}
1910
1911/* must be called iwth out->lock locked */
1912static void stop_compressed_output_l(struct stream_out *out)
1913{
1914 out->offload_state = OFFLOAD_STATE_IDLE;
1915 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001916 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917 if (out->compr != NULL) {
1918 compress_stop(out->compr);
1919 while (out->offload_thread_blocked) {
1920 pthread_cond_wait(&out->cond, &out->lock);
1921 }
1922 }
1923}
1924
1925static void *offload_thread_loop(void *context)
1926{
1927 struct stream_out *out = (struct stream_out *) context;
1928 struct listnode *item;
1929
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001930 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1931 set_sched_policy(0, SP_FOREGROUND);
1932 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1933
1934 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001935
Eric Laurenta1478072015-09-21 17:21:52 -07001936 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001937 out->offload_state = OFFLOAD_STATE_IDLE;
1938 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 for (;;) {
1940 struct offload_cmd *cmd = NULL;
1941 stream_callback_event_t event;
1942 bool send_callback = false;
1943
1944 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1945 __func__, list_empty(&out->offload_cmd_list),
1946 out->offload_state);
1947 if (list_empty(&out->offload_cmd_list)) {
1948 ALOGV("%s SLEEPING", __func__);
1949 pthread_cond_wait(&out->offload_cond, &out->lock);
1950 ALOGV("%s RUNNING", __func__);
1951 continue;
1952 }
1953
1954 item = list_head(&out->offload_cmd_list);
1955 cmd = node_to_item(item, struct offload_cmd, node);
1956 list_remove(item);
1957
1958 ALOGVV("%s STATE %d CMD %d out->compr %p",
1959 __func__, out->offload_state, cmd->cmd, out->compr);
1960
1961 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1962 free(cmd);
1963 break;
1964 }
1965
1966 if (out->compr == NULL) {
1967 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001968 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001969 pthread_cond_signal(&out->cond);
1970 continue;
1971 }
1972 out->offload_thread_blocked = true;
1973 pthread_mutex_unlock(&out->lock);
1974 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001975 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001976 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1977 compress_wait(out->compr, -1);
1978 send_callback = true;
1979 event = STREAM_CBK_EVENT_WRITE_READY;
1980 break;
1981 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001982 compress_next_track(out->compr);
1983 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 send_callback = true;
1985 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001986 /* Resend the metadata for next iteration */
1987 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 break;
1989 case OFFLOAD_CMD_DRAIN:
1990 compress_drain(out->compr);
1991 send_callback = true;
1992 event = STREAM_CBK_EVENT_DRAIN_READY;
1993 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001994 case OFFLOAD_CMD_ERROR:
1995 send_callback = true;
1996 event = STREAM_CBK_EVENT_ERROR;
1997 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001998 default:
1999 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2000 break;
2001 }
Eric Laurenta1478072015-09-21 17:21:52 -07002002 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002003 out->offload_thread_blocked = false;
2004 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002005 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002006 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002008 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 free(cmd);
2010 }
2011
2012 pthread_cond_signal(&out->cond);
2013 while (!list_empty(&out->offload_cmd_list)) {
2014 item = list_head(&out->offload_cmd_list);
2015 list_remove(item);
2016 free(node_to_item(item, struct offload_cmd, node));
2017 }
2018 pthread_mutex_unlock(&out->lock);
2019
2020 return NULL;
2021}
2022
2023static int create_offload_callback_thread(struct stream_out *out)
2024{
2025 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2026 list_init(&out->offload_cmd_list);
2027 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2028 offload_thread_loop, out);
2029 return 0;
2030}
2031
2032static int destroy_offload_callback_thread(struct stream_out *out)
2033{
Eric Laurenta1478072015-09-21 17:21:52 -07002034 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 stop_compressed_output_l(out);
2036 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2037
2038 pthread_mutex_unlock(&out->lock);
2039 pthread_join(out->offload_thread, (void **) NULL);
2040 pthread_cond_destroy(&out->offload_cond);
2041
2042 return 0;
2043}
2044
Eric Laurent07eeafd2013-10-06 12:52:49 -07002045static bool allow_hdmi_channel_config(struct audio_device *adev)
2046{
2047 struct listnode *node;
2048 struct audio_usecase *usecase;
2049 bool ret = true;
2050
2051 list_for_each(node, &adev->usecase_list) {
2052 usecase = node_to_item(node, struct audio_usecase, list);
2053 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2054 /*
2055 * If voice call is already existing, do not proceed further to avoid
2056 * disabling/enabling both RX and TX devices, CSD calls, etc.
2057 * Once the voice call done, the HDMI channels can be configured to
2058 * max channels of remaining use cases.
2059 */
2060 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002061 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002062 __func__);
2063 ret = false;
2064 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002065 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2066 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002067 "no change in HDMI channels", __func__);
2068 ret = false;
2069 break;
2070 }
2071 }
2072 }
2073 return ret;
2074}
2075
2076static int check_and_set_hdmi_channels(struct audio_device *adev,
2077 unsigned int channels)
2078{
2079 struct listnode *node;
2080 struct audio_usecase *usecase;
2081
2082 /* Check if change in HDMI channel config is allowed */
2083 if (!allow_hdmi_channel_config(adev))
2084 return 0;
2085
2086 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002087 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002088 return 0;
2089 }
2090
2091 platform_set_hdmi_channels(adev->platform, channels);
2092 adev->cur_hdmi_channels = channels;
2093
2094 /*
2095 * Deroute all the playback streams routed to HDMI so that
2096 * the back end is deactivated. Note that backend will not
2097 * be deactivated if any one stream is connected to it.
2098 */
2099 list_for_each(node, &adev->usecase_list) {
2100 usecase = node_to_item(node, struct audio_usecase, list);
2101 if (usecase->type == PCM_PLAYBACK &&
2102 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002103 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002104 }
2105 }
2106
2107 /*
2108 * Enable all the streams disabled above. Now the HDMI backend
2109 * will be activated with new channel configuration
2110 */
2111 list_for_each(node, &adev->usecase_list) {
2112 usecase = node_to_item(node, struct audio_usecase, list);
2113 if (usecase->type == PCM_PLAYBACK &&
2114 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002115 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002116 }
2117 }
2118
2119 return 0;
2120}
2121
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002122static int check_and_set_usb_service_interval(struct audio_device *adev,
2123 struct audio_usecase *uc_info,
2124 bool min)
2125{
2126 struct listnode *node;
2127 struct audio_usecase *usecase;
2128 bool switch_usecases = false;
2129 bool reconfig = false;
2130
2131 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2132 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2133 return -1;
2134
2135 /* set if the valid usecase do not already exist */
2136 list_for_each(node, &adev->usecase_list) {
2137 usecase = node_to_item(node, struct audio_usecase, list);
2138 if (usecase->type == PCM_PLAYBACK &&
2139 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2140 switch (usecase->id) {
2141 case USECASE_AUDIO_PLAYBACK_MMAP:
2142 case USECASE_AUDIO_PLAYBACK_ULL:
2143 // cannot reconfig while mmap/ull is present.
2144 return -1;
2145 default:
2146 switch_usecases = true;
2147 break;
2148 }
2149 }
2150 if (switch_usecases)
2151 break;
2152 }
2153 /*
2154 * client can try to set service interval in start_output_stream
2155 * to min or to 0 (i.e reset) in stop_output_stream .
2156 */
2157 unsigned long service_interval =
2158 audio_extn_usb_find_service_interval(min, true /*playback*/);
2159 int ret = platform_set_usb_service_interval(adev->platform,
2160 true /*playback*/,
2161 service_interval,
2162 &reconfig);
2163 /* no change or not supported or no active usecases */
2164 if (ret || !reconfig || !switch_usecases)
2165 return -1;
2166 return 0;
2167#undef VALID_USECASE
2168}
2169
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170static int stop_output_stream(struct stream_out *out)
2171{
2172 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173 struct audio_usecase *uc_info;
2174 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002175 bool has_voip_usecase =
2176 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177
Eric Laurent994a6932013-07-17 11:51:42 -07002178 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002179 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 uc_info = get_usecase_from_list(adev, out->usecase);
2181 if (uc_info == NULL) {
2182 ALOGE("%s: Could not find the usecase (%d) in the list",
2183 __func__, out->usecase);
2184 return -EINVAL;
2185 }
2186
Haynes Mathew George41f86652014-06-17 14:22:15 -07002187 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2188 if (adev->visualizer_stop_output != NULL)
2189 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2190 if (adev->offload_effects_stop_output != NULL)
2191 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002192 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2193 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2194 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002195 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002196
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002197 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2198 voice_set_device_mute_flag(adev, false);
2199
Eric Laurent150dbfe2013-02-27 14:31:02 -08002200 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002201 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002202
2203 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002204 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002206 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Eric Laurent0499d4f2014-08-25 22:39:29 -05002208 audio_extn_extspk_update(adev->extspk);
2209
Eric Laurent07eeafd2013-10-06 12:52:49 -07002210 /* Must be called after removing the usecase from list */
2211 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2212 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002213 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002214 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2215 if (ret == 0) {
2216 /* default service interval was successfully updated,
2217 reopen USB backend with new service interval */
2218 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2219 }
2220 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002221 }
juyuchend194b432018-11-16 14:15:16 +08002222 /* 1) media + voip output routing to handset must route media back to
2223 speaker when voip stops.
2224 2) trigger voip input to reroute when voip output changes to
2225 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002226 if (has_voip_usecase ||
2227 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2228 struct listnode *node;
2229 struct audio_usecase *usecase;
2230 list_for_each(node, &adev->usecase_list) {
2231 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002232 if ((usecase->type == PCM_CAPTURE &&
2233 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2234 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002235 continue;
2236
2237 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2238 __func__, usecase->id, use_case_table[usecase->id],
2239 out->usecase, use_case_table[out->usecase]);
2240 select_devices(adev, usecase->id);
2241 }
2242 }
2243
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002244 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002245 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246 return ret;
2247}
2248
2249int start_output_stream(struct stream_out *out)
2250{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 struct audio_usecase *uc_info;
2253 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002254 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255
Eric Laurent994a6932013-07-17 11:51:42 -07002256 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002258
2259 if (out->card_status == CARD_STATUS_OFFLINE ||
2260 adev->card_status == CARD_STATUS_OFFLINE) {
2261 ALOGW("out->card_status or adev->card_status offline, try again");
2262 ret = -EAGAIN;
2263 goto error_config;
2264 }
2265
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002266 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2267 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002268 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002269 a2dp_combo = true;
2270 } else {
2271 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2272 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2273 ret = -EAGAIN;
2274 goto error_config;
2275 }
2276 }
2277 }
2278 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002279 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 if (out->pcm_device_id < 0) {
2281 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2282 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002283 ret = -EINVAL;
2284 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 }
2286
2287 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2288 uc_info->id = out->usecase;
2289 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002290 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 uc_info->devices = out->devices;
2292 uc_info->in_snd_device = SND_DEVICE_NONE;
2293 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294
Eric Laurent07eeafd2013-10-06 12:52:49 -07002295 /* This must be called before adding this usecase to the list */
2296 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2297 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002298 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2299 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2300 /* USB backend is not reopened immediately.
2301 This is eventually done as part of select_devices */
2302 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002303
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002304 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305
Wei Wangf4837d52017-11-21 14:51:20 -08002306 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002307 audio_extn_perf_lock_acquire();
2308
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002309 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2310 (!audio_extn_a2dp_is_ready())) {
2311 if (!a2dp_combo) {
2312 check_a2dp_restore_l(adev, out, false);
2313 } else {
2314 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002315 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2316 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2317 else
2318 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002319 select_devices(adev, out->usecase);
2320 out->devices = dev;
2321 }
2322 } else {
2323 select_devices(adev, out->usecase);
2324 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002325
Eric Laurent0499d4f2014-08-25 22:39:29 -05002326 audio_extn_extspk_update(adev->extspk);
2327
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002328 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2329 voice_set_device_mute_flag(adev, true);
2330
Andy Hung31aca912014-03-20 17:14:59 -07002331 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002332 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002333 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2334 out->pcm = NULL;
2335 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2336 COMPRESS_IN, &out->compr_config);
2337 if (out->compr && !is_compress_ready(out->compr)) {
2338 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2339 compress_close(out->compr);
2340 out->compr = NULL;
2341 ret = -EIO;
2342 goto error_open;
2343 }
2344 if (out->offload_callback)
2345 compress_nonblock(out->compr, out->non_blocking);
2346
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002347 if (adev->visualizer_start_output != NULL) {
2348 int capture_device_id =
2349 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2350 PCM_CAPTURE);
2351 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2352 adev->snd_card, capture_device_id);
2353 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002354 if (adev->offload_effects_start_output != NULL)
2355 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2356 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002357 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002358 ALOGE("%s: pcm stream not ready", __func__);
2359 goto error_open;
2360 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002361 ret = pcm_start(out->pcm);
2362 if (ret < 0) {
2363 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2364 goto error_open;
2365 }
2366 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002367 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002368 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002369
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002370 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2371 flags |= PCM_MMAP | PCM_NOIRQ;
2372 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002373 } else if (out->realtime) {
2374 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002375 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002376
2377 while (1) {
2378 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2379 flags, &out->config);
2380 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2381 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2382 if (out->pcm != NULL) {
2383 pcm_close(out->pcm);
2384 out->pcm = NULL;
2385 }
2386 if (pcm_open_retry_count-- == 0) {
2387 ret = -EIO;
2388 goto error_open;
2389 }
2390 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2391 continue;
2392 }
2393 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002395 ALOGV("%s: pcm_prepare", __func__);
2396 if (pcm_is_ready(out->pcm)) {
2397 ret = pcm_prepare(out->pcm);
2398 if (ret < 0) {
2399 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2400 pcm_close(out->pcm);
2401 out->pcm = NULL;
2402 goto error_open;
2403 }
2404 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002405 if (out->realtime) {
2406 ret = pcm_start(out->pcm);
2407 if (ret < 0) {
2408 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2409 pcm_close(out->pcm);
2410 out->pcm = NULL;
2411 goto error_open;
2412 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002413 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002414 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002415 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002416 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002417 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002418 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002419
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002420 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2421 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2422 audio_low_latency_hint_start();
2423 }
2424
vivek mehtae59cfb22017-06-16 15:57:11 -07002425 // consider a scenario where on pause lower layers are tear down.
2426 // so on resume, swap mixer control need to be sent only when
2427 // backend is active, hence rather than sending from enable device
2428 // sending it from start of streamtream
2429
2430 platform_set_swap_channels(adev, true);
2431
Eric Laurent994a6932013-07-17 11:51:42 -07002432 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002433 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002435 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002436 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002438error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002439 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440}
2441
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442static int check_input_parameters(uint32_t sample_rate,
2443 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002444 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002446 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2447 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002448 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2449 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002450 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2451 return -EINVAL;
2452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Eric Laurent74b55762017-07-09 17:04:53 -07002454 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2455 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002456 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002457 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002458 return -EINVAL;
2459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460
2461 switch (sample_rate) {
2462 case 8000:
2463 case 11025:
2464 case 12000:
2465 case 16000:
2466 case 22050:
2467 case 24000:
2468 case 32000:
2469 case 44100:
2470 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002471 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 break;
2473 default:
vivek mehtadae44712015-07-27 14:13:18 -07002474 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 return -EINVAL;
2476 }
2477
2478 return 0;
2479}
2480
Kevin Rocarda325aa22018-04-03 09:15:52 -07002481/** Add a value in a list if not already present.
2482 * @return true if value was successfully inserted or already present,
2483 * false if the list is full and does not contain the value.
2484 */
2485static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2486 for (size_t i = 0; i < list_length; i++) {
2487 if (list[i] == value) return true; // value is already present
2488 if (list[i] == 0) { // no values in this slot
2489 list[i] = value;
2490 return true; // value inserted
2491 }
2492 }
2493 return false; // could not insert value
2494}
2495
2496/** Add channel_mask in supported_channel_masks if not already present.
2497 * @return true if channel_mask was successfully inserted or already present,
2498 * false if supported_channel_masks is full and does not contain channel_mask.
2499 */
2500static void register_channel_mask(audio_channel_mask_t channel_mask,
2501 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2502 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2503 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2504}
2505
2506/** Add format in supported_formats if not already present.
2507 * @return true if format was successfully inserted or already present,
2508 * false if supported_formats is full and does not contain format.
2509 */
2510static void register_format(audio_format_t format,
2511 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2512 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2513 "%s: stream can not declare supporting its format %x", __func__, format);
2514}
2515/** Add sample_rate in supported_sample_rates if not already present.
2516 * @return true if sample_rate was successfully inserted or already present,
2517 * false if supported_sample_rates is full and does not contain sample_rate.
2518 */
2519static void register_sample_rate(uint32_t sample_rate,
2520 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2521 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2522 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2523}
2524
vivek mehtaa68fea62017-06-08 19:04:02 -07002525static size_t get_stream_buffer_size(size_t duration_ms,
2526 uint32_t sample_rate,
2527 audio_format_t format,
2528 int channel_count,
2529 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530{
2531 size_t size = 0;
2532
vivek mehtaa68fea62017-06-08 19:04:02 -07002533 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002534 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002535 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002536
2537 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538
Glenn Kasten4f993392014-05-14 07:30:48 -07002539 /* make sure the size is multiple of 32 bytes
2540 * At 48 kHz mono 16-bit PCM:
2541 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2542 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2543 */
2544 size += 0x1f;
2545 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002546
2547 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548}
2549
2550static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2551{
2552 struct stream_out *out = (struct stream_out *)stream;
2553
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002554 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555}
2556
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002557static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558{
2559 return -ENOSYS;
2560}
2561
2562static size_t out_get_buffer_size(const struct audio_stream *stream)
2563{
2564 struct stream_out *out = (struct stream_out *)stream;
2565
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2567 return out->compr_config.fragment_size;
2568 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002569 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002570 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571}
2572
2573static uint32_t out_get_channels(const struct audio_stream *stream)
2574{
2575 struct stream_out *out = (struct stream_out *)stream;
2576
2577 return out->channel_mask;
2578}
2579
2580static audio_format_t out_get_format(const struct audio_stream *stream)
2581{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 struct stream_out *out = (struct stream_out *)stream;
2583
2584 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585}
2586
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002587static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588{
2589 return -ENOSYS;
2590}
2591
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002592/* must be called with out->lock locked */
2593static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594{
2595 struct stream_out *out = (struct stream_out *)stream;
2596 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002597 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002600 if (adev->adm_deregister_stream)
2601 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002602 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2605 if (out->pcm) {
2606 pcm_close(out->pcm);
2607 out->pcm = NULL;
2608 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002609 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002610 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002611 out->playback_started = false;
2612 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613 } else {
2614 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002615 out->gapless_mdata.encoder_delay = 0;
2616 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 if (out->compr != NULL) {
2618 compress_close(out->compr);
2619 out->compr = NULL;
2620 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002621 }
Phil Burkbc991042017-02-24 08:06:44 -08002622 if (do_stop) {
2623 stop_output_stream(out);
2624 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002625 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002626 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002627 return 0;
2628}
2629
2630static int out_standby(struct audio_stream *stream)
2631{
2632 struct stream_out *out = (struct stream_out *)stream;
2633
2634 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2635 out->usecase, use_case_table[out->usecase]);
2636
2637 lock_output_stream(out);
2638 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002640 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 return 0;
2642}
2643
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002644static int out_on_error(struct audio_stream *stream)
2645{
2646 struct stream_out *out = (struct stream_out *)stream;
2647 struct audio_device *adev = out->dev;
2648 bool do_standby = false;
2649
2650 lock_output_stream(out);
2651 if (!out->standby) {
2652 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2653 stop_compressed_output_l(out);
2654 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2655 } else
2656 do_standby = true;
2657 }
2658 pthread_mutex_unlock(&out->lock);
2659
2660 if (do_standby)
2661 return out_standby(&out->stream.common);
2662
2663 return 0;
2664}
2665
Andy Hung7401c7c2016-09-21 12:41:21 -07002666static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667{
Andy Hung7401c7c2016-09-21 12:41:21 -07002668 struct stream_out *out = (struct stream_out *)stream;
2669
2670 // We try to get the lock for consistency,
2671 // but it isn't necessary for these variables.
2672 // If we're not in standby, we may be blocked on a write.
2673 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2674 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2675 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2676
2677 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002678 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002679 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002680
2681 // dump error info
2682 (void)error_log_dump(
2683 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 return 0;
2686}
2687
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002688static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2689{
2690 int ret = 0;
2691 char value[32];
2692 struct compr_gapless_mdata tmp_mdata;
2693
2694 if (!out || !parms) {
2695 return -EINVAL;
2696 }
2697
2698 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2699 if (ret >= 0) {
2700 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2701 } else {
2702 return -EINVAL;
2703 }
2704
2705 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2706 if (ret >= 0) {
2707 tmp_mdata.encoder_padding = atoi(value);
2708 } else {
2709 return -EINVAL;
2710 }
2711
2712 out->gapless_mdata = tmp_mdata;
2713 out->send_new_metadata = 1;
2714 ALOGV("%s new encoder delay %u and padding %u", __func__,
2715 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2716
2717 return 0;
2718}
2719
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002720static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2721{
2722 return out == adev->primary_output || out == adev->voice_tx_output;
2723}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002724
Kevin Rocard1e02c882017-08-09 15:26:07 -07002725static int get_alive_usb_card(struct str_parms* parms) {
2726 int card;
2727 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2728 !audio_extn_usb_alive(card)) {
2729 return card;
2730 }
2731 return -ENODEV;
2732}
2733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2735{
2736 struct stream_out *out = (struct stream_out *)stream;
2737 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002738 struct audio_usecase *usecase;
2739 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 struct str_parms *parms;
2741 char value[32];
2742 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002743 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002744 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002745 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746
Eric Laurent2e140aa2016-06-30 17:14:46 -07002747 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002748 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 parms = str_parms_create_str(kvpairs);
2750 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2751 if (ret >= 0) {
2752 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002753
Eric Laurenta1478072015-09-21 17:21:52 -07002754 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002755
2756 // The usb driver needs to be closed after usb device disconnection
2757 // otherwise audio is no longer played on the new usb devices.
2758 // By forcing the stream in standby, the usb stack refcount drops to 0
2759 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002760 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002761 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002762 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2763 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2764 out_standby_l(&out->stream.common);
2765 }
2766 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002767 }
2768
Eric Laurent150dbfe2013-02-27 14:31:02 -08002769 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002771 /*
2772 * When HDMI cable is unplugged the music playback is paused and
2773 * the policy manager sends routing=0. But the audioflinger
2774 * continues to write data until standby time (3sec).
2775 * As the HDMI core is turned off, the write gets blocked.
2776 * Avoid this by routing audio to speaker until standby.
2777 */
2778 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2779 val == AUDIO_DEVICE_NONE) {
2780 val = AUDIO_DEVICE_OUT_SPEAKER;
2781 }
2782
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002783 /*
2784 * When A2DP is disconnected the
2785 * music playback is paused and the policy manager sends routing=0
2786 * But the audioflingercontinues to write data until standby time
2787 * (3sec). As BT is turned off, the write gets blocked.
2788 * Avoid this by routing audio to speaker until standby.
2789 */
2790 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2791 (val == AUDIO_DEVICE_NONE) &&
2792 !audio_extn_a2dp_is_ready()) {
2793 val = AUDIO_DEVICE_OUT_SPEAKER;
2794 }
2795
2796 /* To avoid a2dp to sco overlapping / BT device improper state
2797 * check with BT lib about a2dp streaming support before routing
2798 */
2799 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2800 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002801 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002802 //combo usecase just by pass a2dp
2803 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2804 bypass_a2dp = true;
2805 } else {
2806 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2807 /* update device to a2dp and don't route as BT returned error
2808 * However it is still possible a2dp routing called because
2809 * of current active device disconnection (like wired headset)
2810 */
2811 out->devices = val;
2812 pthread_mutex_unlock(&out->lock);
2813 pthread_mutex_unlock(&adev->lock);
2814 status = -ENOSYS;
2815 goto routing_fail;
2816 }
2817 }
2818 }
2819
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002820 audio_devices_t new_dev = val;
2821
2822 // Workaround: If routing to an non existing usb device, fail gracefully
2823 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002824 int card;
2825 if (audio_is_usb_out_device(new_dev) &&
2826 (card = get_alive_usb_card(parms)) >= 0) {
2827
2828 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002829 pthread_mutex_unlock(&adev->lock);
2830 pthread_mutex_unlock(&out->lock);
2831 status = -ENOSYS;
2832 goto routing_fail;
2833 }
2834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002835 /*
2836 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002837 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002838 * the select_devices(). But how do we undo this?
2839 *
2840 * For example, music playback is active on headset (deep-buffer usecase)
2841 * and if we go to ringtones and select a ringtone, low-latency usecase
2842 * will be started on headset+speaker. As we can't enable headset+speaker
2843 * and headset devices at the same time, select_devices() switches the music
2844 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2845 * So when the ringtone playback is completed, how do we undo the same?
2846 *
2847 * We are relying on the out_set_parameters() call on deep-buffer output,
2848 * once the ringtone playback is ended.
2849 * NOTE: We should not check if the current devices are same as new devices.
2850 * Because select_devices() must be called to switch back the music
2851 * playback to headset.
2852 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002853 if (new_dev != AUDIO_DEVICE_NONE) {
2854 bool same_dev = out->devices == new_dev;
2855 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002856
Eric Laurenta7657192014-10-09 21:09:33 -07002857 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002858 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002859 if (adev->mode == AUDIO_MODE_IN_CALL) {
2860 adev->current_call_output = out;
2861 ret = voice_start_call(adev);
2862 }
2863 } else {
2864 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002865 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002866 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002867 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002868
2869 if (!out->standby) {
2870 if (!same_dev) {
2871 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002872 // inform adm before actual routing to prevent glitches.
2873 if (adev->adm_on_routing_change) {
2874 adev->adm_on_routing_change(adev->adm_data,
2875 out->handle);
2876 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002877 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002878 if (!bypass_a2dp) {
2879 select_devices(adev, out->usecase);
2880 } else {
juyuchen9baad392018-06-05 19:02:10 +08002881 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2882 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2883 else
2884 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002885 select_devices(adev, out->usecase);
2886 out->devices = new_dev;
2887 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002888 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002889
2890 // on device switch force swap, lower functions will make sure
2891 // to check if swap is allowed or not.
2892
2893 if (!same_dev)
2894 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002895
2896 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2897 out->a2dp_compress_mute &&
2898 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2899 pthread_mutex_lock(&out->compr_mute_lock);
2900 out->a2dp_compress_mute = false;
2901 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2902 pthread_mutex_unlock(&out->compr_mute_lock);
2903 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002904 }
2905
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002906 }
2907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002908 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002909 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002910
2911 /*handles device and call state changes*/
2912 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002914 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002915
2916 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2917 parse_compress_metadata(out, parms);
2918 }
2919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002921 ALOGV("%s: exit: code(%d)", __func__, status);
2922 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002923}
2924
Haynes Mathew George569b7482017-05-08 14:44:27 -07002925static bool stream_get_parameter_channels(struct str_parms *query,
2926 struct str_parms *reply,
2927 audio_channel_mask_t *supported_channel_masks) {
2928 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002929 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002930 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002931 size_t i, j;
2932
2933 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2934 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 value[0] = '\0';
2936 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002937 while (supported_channel_masks[i] != 0) {
2938 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2939 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002940 if (!first) {
2941 strcat(value, "|");
2942 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002943 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944 first = false;
2945 break;
2946 }
2947 }
2948 i++;
2949 }
2950 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002951 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002952 return ret >= 0;
2953}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002954
Haynes Mathew George569b7482017-05-08 14:44:27 -07002955static bool stream_get_parameter_formats(struct str_parms *query,
2956 struct str_parms *reply,
2957 audio_format_t *supported_formats) {
2958 int ret = -1;
2959 char value[256];
2960 int i;
2961
2962 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2963 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002964 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002965 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002966 case AUDIO_FORMAT_PCM_16_BIT:
2967 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2968 break;
2969 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2970 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2971 break;
2972 case AUDIO_FORMAT_PCM_32_BIT:
2973 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2974 break;
2975 default:
2976 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002977 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002978 break;
2979 }
2980 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002981 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002982 return ret >= 0;
2983}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002984
Haynes Mathew George569b7482017-05-08 14:44:27 -07002985static bool stream_get_parameter_rates(struct str_parms *query,
2986 struct str_parms *reply,
2987 uint32_t *supported_sample_rates) {
2988
2989 int i;
2990 char value[256];
2991 int ret = -1;
2992 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2993 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002994 value[0] = '\0';
2995 i=0;
2996 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002997 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002998 int avail = sizeof(value) - cursor;
2999 ret = snprintf(value + cursor, avail, "%s%d",
3000 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003001 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003002 if (ret < 0 || ret >= avail) {
3003 // if cursor is at the last element of the array
3004 // overwrite with \0 is duplicate work as
3005 // snprintf already put a \0 in place.
3006 // else
3007 // we had space to write the '|' at value[cursor]
3008 // (which will be overwritten) or no space to fill
3009 // the first element (=> cursor == 0)
3010 value[cursor] = '\0';
3011 break;
3012 }
3013 cursor += ret;
3014 ++i;
3015 }
3016 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3017 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003018 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003019 return ret >= 0;
3020}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003021
Haynes Mathew George569b7482017-05-08 14:44:27 -07003022static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3023{
3024 struct stream_out *out = (struct stream_out *)stream;
3025 struct str_parms *query = str_parms_create_str(keys);
3026 char *str;
3027 struct str_parms *reply = str_parms_create();
3028 bool replied = false;
3029 ALOGV("%s: enter: keys - %s", __func__, keys);
3030
3031 replied |= stream_get_parameter_channels(query, reply,
3032 &out->supported_channel_masks[0]);
3033 replied |= stream_get_parameter_formats(query, reply,
3034 &out->supported_formats[0]);
3035 replied |= stream_get_parameter_rates(query, reply,
3036 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003037 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 str = str_parms_to_str(reply);
3039 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003040 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 }
3042 str_parms_destroy(query);
3043 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003044 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 return str;
3046}
3047
3048static uint32_t out_get_latency(const struct audio_stream_out *stream)
3049{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003050 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003052 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003054 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3055 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003056 else if ((out->realtime) ||
3057 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003058 // since the buffer won't be filled up faster than realtime,
3059 // return a smaller number
3060 period_ms = (out->af_period_multiplier * out->config.period_size *
3061 1000) / (out->config.rate);
3062 hw_delay = platform_render_latency(out->usecase)/1000;
3063 return period_ms + hw_delay;
3064 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003065
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003066 latency = (out->config.period_count * out->config.period_size * 1000) /
3067 (out->config.rate);
3068
3069 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3070 latency += audio_extn_a2dp_get_encoder_latency();
3071
3072 return latency;
3073}
3074
3075static int set_compr_volume(struct audio_stream_out *stream, float left,
3076 float right)
3077{
3078 struct stream_out *out = (struct stream_out *)stream;
3079 int volume[2];
3080 char mixer_ctl_name[128];
3081 struct audio_device *adev = out->dev;
3082 struct mixer_ctl *ctl;
3083 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3084 PCM_PLAYBACK);
3085
3086 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3087 "Compress Playback %d Volume", pcm_device_id);
3088 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3089 if (!ctl) {
3090 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3091 __func__, mixer_ctl_name);
3092 return -EINVAL;
3093 }
3094 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3095 __func__, mixer_ctl_name, left, right);
3096 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3097 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3098 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3099
3100 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101}
3102
3103static int out_set_volume(struct audio_stream_out *stream, float left,
3104 float right)
3105{
Eric Laurenta9024de2013-04-04 09:19:12 -07003106 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003107 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003108
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003109 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003110 /* only take left channel into account: the API is for stereo anyway */
3111 out->muted = (left == 0.0f);
3112 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003113 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003114 pthread_mutex_lock(&out->compr_mute_lock);
3115 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3116 if (!out->a2dp_compress_mute)
3117 ret = set_compr_volume(stream, left, right);
3118 out->volume_l = left;
3119 out->volume_r = right;
3120 pthread_mutex_unlock(&out->compr_mute_lock);
3121 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003122 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003123 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3124 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3125 if (!out->standby) {
3126 // if in standby, cached volume will be sent after stream is opened
3127 audio_extn_utils_send_app_type_gain(out->dev,
3128 out->app_type_cfg.app_type,
3129 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003130 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003131 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003132 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 return -ENOSYS;
3135}
3136
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003137// note: this call is safe only if the stream_cb is
3138// removed first in close_output_stream (as is done now).
3139static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3140{
3141 if (!stream || !parms)
3142 return;
3143
3144 struct stream_out *out = (struct stream_out *)stream;
3145 struct audio_device *adev = out->dev;
3146
3147 card_status_t status;
3148 int card;
3149 if (parse_snd_card_status(parms, &card, &status) < 0)
3150 return;
3151
3152 pthread_mutex_lock(&adev->lock);
3153 bool valid_cb = (card == adev->snd_card);
3154 pthread_mutex_unlock(&adev->lock);
3155
3156 if (!valid_cb)
3157 return;
3158
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003159 lock_output_stream(out);
3160 if (out->card_status != status)
3161 out->card_status = status;
3162 pthread_mutex_unlock(&out->lock);
3163
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003164 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3165 use_case_table[out->usecase],
3166 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3167
3168 if (status == CARD_STATUS_OFFLINE)
3169 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003170
3171 return;
3172}
3173
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003174#ifdef NO_AUDIO_OUT
3175static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003176 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003177{
3178 struct stream_out *out = (struct stream_out *)stream;
3179
3180 /* No Output device supported other than BT for playback.
3181 * Sleep for the amount of buffer duration
3182 */
Eric Laurenta1478072015-09-21 17:21:52 -07003183 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003184 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3185 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003186 out_get_sample_rate(&out->stream.common));
3187 pthread_mutex_unlock(&out->lock);
3188 return bytes;
3189}
3190#endif
3191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3193 size_t bytes)
3194{
3195 struct stream_out *out = (struct stream_out *)stream;
3196 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003197 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003198 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurenta1478072015-09-21 17:21:52 -07003200 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003201 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003202 const size_t frame_size = audio_stream_out_frame_size(stream);
3203 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003204
Eric Laurent0e46adf2016-12-16 12:49:24 -08003205 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3206 error_code = ERROR_CODE_WRITE;
3207 goto exit;
3208 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003209
3210 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3211 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003212 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003213 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3214 ret = -EIO;
3215 goto exit;
3216 }
3217 }
3218 }
3219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003221 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003222 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003224
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003227 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003228 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229 goto exit;
3230 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003231
vivek mehta40125092017-08-21 18:48:51 -07003232 // after standby always force set last known cal step
3233 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3234 ALOGD("%s: retry previous failed cal level set", __func__);
3235 send_gain_dep_calibration_l();
3236 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003240 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003241 if (out->send_new_metadata) {
3242 ALOGVV("send new gapless metadata");
3243 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3244 out->send_new_metadata = 0;
3245 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003246 unsigned int avail;
3247 struct timespec tstamp;
3248 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3249 /* Do not limit write size if the available frames count is unknown */
3250 if (ret != 0) {
3251 avail = bytes;
3252 }
3253 if (avail == 0) {
3254 ret = 0;
3255 } else {
3256 if (avail > bytes) {
3257 avail = bytes;
3258 }
3259 ret = compress_write(out->compr, buffer, avail);
3260 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3261 __func__, avail, ret);
3262 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003263
Eric Laurent6e895242013-09-05 16:10:57 -07003264 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003265 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3266 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003267 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003268 compress_start(out->compr);
3269 out->playback_started = 1;
3270 out->offload_state = OFFLOAD_STATE_PLAYING;
3271 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003272 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003273 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003274 } else {
3275 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003276 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003277 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003278 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 return ret;
3280 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003281 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003282 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003283 size_t bytes_to_write = bytes;
3284
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 if (out->muted)
3286 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003287 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003288 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003289 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3290 int16_t *src = (int16_t *)buffer;
3291 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003292
Eric Laurentad2dde92017-09-20 18:27:31 -07003293 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3294 out->format != AUDIO_FORMAT_PCM_16_BIT,
3295 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003296
Eric Laurentad2dde92017-09-20 18:27:31 -07003297 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3298 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3299 }
3300 bytes_to_write /= 2;
3301 }
3302 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
3303
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003304 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003305 request_out_focus(out, ns);
3306
3307 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3308 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003309 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003310 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003311 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003312
Haynes Mathew George03c40102016-01-29 17:57:48 -08003313 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003314 } else {
3315 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003316 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317 }
3318
3319exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003320 // For PCM we always consume the buffer and return #bytes regardless of ret.
3321 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003322 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003323 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003324 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003325
Andy Hung7401c7c2016-09-21 12:41:21 -07003326 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003327 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003328 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3329 ALOGE_IF(out->pcm != NULL,
3330 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003331 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003332 // usleep not guaranteed for values over 1 second but we don't limit here.
3333 }
3334 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 pthread_mutex_unlock(&out->lock);
3337
3338 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003339 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003340 if (sleeptime_us != 0)
3341 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 }
3343 return bytes;
3344}
3345
3346static int out_get_render_position(const struct audio_stream_out *stream,
3347 uint32_t *dsp_frames)
3348{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003349 struct stream_out *out = (struct stream_out *)stream;
3350 *dsp_frames = 0;
3351 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003352 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003353 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003354 unsigned long frames = 0;
3355 // TODO: check return value
3356 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3357 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003358 ALOGVV("%s rendered frames %d sample_rate %d",
3359 __func__, *dsp_frames, out->sample_rate);
3360 }
3361 pthread_mutex_unlock(&out->lock);
3362 return 0;
3363 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003364 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365}
3366
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003367static int out_add_audio_effect(const struct audio_stream *stream __unused,
3368 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369{
3370 return 0;
3371}
3372
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003373static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3374 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375{
3376 return 0;
3377}
3378
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003379static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3380 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003382 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383}
3384
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003385static int out_get_presentation_position(const struct audio_stream_out *stream,
3386 uint64_t *frames, struct timespec *timestamp)
3387{
3388 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003389 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003390 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003391
Eric Laurenta1478072015-09-21 17:21:52 -07003392 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003393
Eric Laurent949a0892013-09-20 09:20:13 -07003394 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3395 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003396 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003397 compress_get_tstamp(out->compr, &dsp_frames,
3398 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003399 // Adjustment accounts for A2DP encoder latency with offload usecases
3400 // Note: Encoder latency is returned in ms.
3401 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3402 unsigned long offset =
3403 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3404 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3405 }
Eric Laurent949a0892013-09-20 09:20:13 -07003406 ALOGVV("%s rendered frames %ld sample_rate %d",
3407 __func__, dsp_frames, out->sample_rate);
3408 *frames = dsp_frames;
3409 ret = 0;
3410 /* this is the best we can do */
3411 clock_gettime(CLOCK_MONOTONIC, timestamp);
3412 }
3413 } else {
3414 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003415 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003416 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3417 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003418 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003419 // This adjustment accounts for buffering after app processor.
3420 // It is based on estimated DSP latency per use case, rather than exact.
3421 signed_frames -=
3422 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3423
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003424 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3425 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3426 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3427 signed_frames -=
3428 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3429 }
3430
Eric Laurent949a0892013-09-20 09:20:13 -07003431 // It would be unusual for this value to be negative, but check just in case ...
3432 if (signed_frames >= 0) {
3433 *frames = signed_frames;
3434 ret = 0;
3435 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003436 }
3437 }
3438 }
3439
3440 pthread_mutex_unlock(&out->lock);
3441
3442 return ret;
3443}
3444
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003445static int out_set_callback(struct audio_stream_out *stream,
3446 stream_callback_t callback, void *cookie)
3447{
3448 struct stream_out *out = (struct stream_out *)stream;
3449
3450 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003451 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003452 out->offload_callback = callback;
3453 out->offload_cookie = cookie;
3454 pthread_mutex_unlock(&out->lock);
3455 return 0;
3456}
3457
3458static int out_pause(struct audio_stream_out* stream)
3459{
3460 struct stream_out *out = (struct stream_out *)stream;
3461 int status = -ENOSYS;
3462 ALOGV("%s", __func__);
3463 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003464 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3466 status = compress_pause(out->compr);
3467 out->offload_state = OFFLOAD_STATE_PAUSED;
3468 }
3469 pthread_mutex_unlock(&out->lock);
3470 }
3471 return status;
3472}
3473
3474static int out_resume(struct audio_stream_out* stream)
3475{
3476 struct stream_out *out = (struct stream_out *)stream;
3477 int status = -ENOSYS;
3478 ALOGV("%s", __func__);
3479 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3480 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003481 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3483 status = compress_resume(out->compr);
3484 out->offload_state = OFFLOAD_STATE_PLAYING;
3485 }
3486 pthread_mutex_unlock(&out->lock);
3487 }
3488 return status;
3489}
3490
3491static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3492{
3493 struct stream_out *out = (struct stream_out *)stream;
3494 int status = -ENOSYS;
3495 ALOGV("%s", __func__);
3496 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003497 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3499 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3500 else
3501 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3502 pthread_mutex_unlock(&out->lock);
3503 }
3504 return status;
3505}
3506
3507static int out_flush(struct audio_stream_out* stream)
3508{
3509 struct stream_out *out = (struct stream_out *)stream;
3510 ALOGV("%s", __func__);
3511 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003512 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003513 stop_compressed_output_l(out);
3514 pthread_mutex_unlock(&out->lock);
3515 return 0;
3516 }
3517 return -ENOSYS;
3518}
3519
Eric Laurent0e46adf2016-12-16 12:49:24 -08003520static int out_stop(const struct audio_stream_out* stream)
3521{
3522 struct stream_out *out = (struct stream_out *)stream;
3523 struct audio_device *adev = out->dev;
3524 int ret = -ENOSYS;
3525
3526 ALOGV("%s", __func__);
3527 pthread_mutex_lock(&adev->lock);
3528 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3529 out->playback_started && out->pcm != NULL) {
3530 pcm_stop(out->pcm);
3531 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003532 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003533 }
3534 pthread_mutex_unlock(&adev->lock);
3535 return ret;
3536}
3537
3538static int out_start(const struct audio_stream_out* stream)
3539{
3540 struct stream_out *out = (struct stream_out *)stream;
3541 struct audio_device *adev = out->dev;
3542 int ret = -ENOSYS;
3543
3544 ALOGV("%s", __func__);
3545 pthread_mutex_lock(&adev->lock);
3546 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3547 !out->playback_started && out->pcm != NULL) {
3548 ret = start_output_stream(out);
3549 if (ret == 0) {
3550 out->playback_started = true;
3551 }
3552 }
3553 pthread_mutex_unlock(&adev->lock);
3554 return ret;
3555}
3556
Phil Burkbc991042017-02-24 08:06:44 -08003557/*
3558 * Modify config->period_count based on min_size_frames
3559 */
3560static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3561{
3562 int periodCountRequested = (min_size_frames + config->period_size - 1)
3563 / config->period_size;
3564 int periodCount = MMAP_PERIOD_COUNT_MIN;
3565
3566 ALOGV("%s original config.period_size = %d config.period_count = %d",
3567 __func__, config->period_size, config->period_count);
3568
3569 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3570 periodCount *= 2;
3571 }
3572 config->period_count = periodCount;
3573
3574 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3575}
3576
Eric Laurent0e46adf2016-12-16 12:49:24 -08003577static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3578 int32_t min_size_frames,
3579 struct audio_mmap_buffer_info *info)
3580{
3581 struct stream_out *out = (struct stream_out *)stream;
3582 struct audio_device *adev = out->dev;
3583 int ret = 0;
3584 unsigned int offset1;
3585 unsigned int frames1;
3586 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003587 uint32_t mmap_size;
3588 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003589
3590 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003591 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003592 pthread_mutex_lock(&adev->lock);
3593
3594 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003595 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003596 ret = -EINVAL;
3597 goto exit;
3598 }
3599 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003600 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003601 ret = -ENOSYS;
3602 goto exit;
3603 }
3604 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3605 if (out->pcm_device_id < 0) {
3606 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3607 __func__, out->pcm_device_id, out->usecase);
3608 ret = -EINVAL;
3609 goto exit;
3610 }
Phil Burkbc991042017-02-24 08:06:44 -08003611
3612 adjust_mmap_period_count(&out->config, min_size_frames);
3613
Eric Laurent0e46adf2016-12-16 12:49:24 -08003614 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3615 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3616 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3617 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3618 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3619 step = "open";
3620 ret = -ENODEV;
3621 goto exit;
3622 }
3623 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3624 if (ret < 0) {
3625 step = "begin";
3626 goto exit;
3627 }
3628 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003629 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003630 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003631 ret = platform_get_mmap_data_fd(adev->platform,
3632 out->pcm_device_id, 0 /*playback*/,
3633 &info->shared_memory_fd,
3634 &mmap_size);
3635 if (ret < 0) {
3636 // Fall back to non exclusive mode
3637 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3638 } else {
3639 if (mmap_size < buffer_size) {
3640 step = "mmap";
3641 goto exit;
3642 }
3643 // FIXME: indicate exclusive mode support by returning a negative buffer size
3644 info->buffer_size_frames *= -1;
3645 }
3646 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003647
3648 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3649 if (ret < 0) {
3650 step = "commit";
3651 goto exit;
3652 }
Phil Burkbc991042017-02-24 08:06:44 -08003653
3654 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003655 ret = 0;
3656
3657 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3658 __func__, info->shared_memory_address, info->buffer_size_frames);
3659
3660exit:
3661 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003662 if (out->pcm == NULL) {
3663 ALOGE("%s: %s - %d", __func__, step, ret);
3664 } else {
3665 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003666 pcm_close(out->pcm);
3667 out->pcm = NULL;
3668 }
3669 }
3670 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003671 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003672 return ret;
3673}
3674
3675static int out_get_mmap_position(const struct audio_stream_out *stream,
3676 struct audio_mmap_position *position)
3677{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003678 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003679 struct stream_out *out = (struct stream_out *)stream;
3680 ALOGVV("%s", __func__);
3681 if (position == NULL) {
3682 return -EINVAL;
3683 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003684 lock_output_stream(out);
3685 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3686 out->pcm == NULL) {
3687 ret = -ENOSYS;
3688 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003689 }
3690
3691 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003692 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003693 if (ret < 0) {
3694 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003695 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003696 }
Andy Hungfc044e12017-03-20 09:24:22 -07003697 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003698exit:
3699 pthread_mutex_unlock(&out->lock);
3700 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003701}
3702
3703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704/** audio_stream_in implementation **/
3705static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3706{
3707 struct stream_in *in = (struct stream_in *)stream;
3708
3709 return in->config.rate;
3710}
3711
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003712static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713{
3714 return -ENOSYS;
3715}
3716
3717static size_t in_get_buffer_size(const struct audio_stream *stream)
3718{
3719 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003720 return in->config.period_size * in->af_period_multiplier *
3721 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722}
3723
3724static uint32_t in_get_channels(const struct audio_stream *stream)
3725{
3726 struct stream_in *in = (struct stream_in *)stream;
3727
3728 return in->channel_mask;
3729}
3730
vivek mehta4ed66e62016-04-15 23:33:34 -07003731static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732{
vivek mehta4ed66e62016-04-15 23:33:34 -07003733 struct stream_in *in = (struct stream_in *)stream;
3734 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735}
3736
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003737static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738{
3739 return -ENOSYS;
3740}
3741
3742static int in_standby(struct audio_stream *stream)
3743{
3744 struct stream_in *in = (struct stream_in *)stream;
3745 struct audio_device *adev = in->dev;
3746 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003747 bool do_stop = true;
3748
Eric Laurent994a6932013-07-17 11:51:42 -07003749 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003750
3751 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003752
3753 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003754 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003755 audio_extn_sound_trigger_stop_lab(in);
3756 in->standby = true;
3757 }
3758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003760 if (adev->adm_deregister_stream)
3761 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3762
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003763 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003765 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003766 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003767 in->capture_started = false;
3768 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003769 if (in->pcm) {
3770 pcm_close(in->pcm);
3771 in->pcm = NULL;
3772 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003773 adev->enable_voicerx = false;
3774 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003775 if (do_stop) {
3776 status = stop_input_stream(in);
3777 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003778 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 }
3780 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003781 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 return status;
3783}
3784
Andy Hungd13f0d32017-06-12 13:58:37 -07003785static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003786{
Andy Hungd13f0d32017-06-12 13:58:37 -07003787 struct stream_in *in = (struct stream_in *)stream;
3788
3789 // We try to get the lock for consistency,
3790 // but it isn't necessary for these variables.
3791 // If we're not in standby, we may be blocked on a read.
3792 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3793 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3794 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3795 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3796
3797 if (locked) {
3798 pthread_mutex_unlock(&in->lock);
3799 }
3800
3801 // dump error info
3802 (void)error_log_dump(
3803 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 return 0;
3805}
3806
3807static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3808{
3809 struct stream_in *in = (struct stream_in *)stream;
3810 struct audio_device *adev = in->dev;
3811 struct str_parms *parms;
3812 char *str;
3813 char value[32];
3814 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003815 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816
Eric Laurent994a6932013-07-17 11:51:42 -07003817 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 parms = str_parms_create_str(kvpairs);
3819
3820 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3821
Eric Laurenta1478072015-09-21 17:21:52 -07003822 lock_input_stream(in);
3823
Eric Laurent150dbfe2013-02-27 14:31:02 -08003824 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 if (ret >= 0) {
3826 val = atoi(value);
3827 /* no audio source uses val == 0 */
3828 if ((in->source != val) && (val != 0)) {
3829 in->source = val;
3830 }
3831 }
3832
3833 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 if (ret >= 0) {
3836 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003837 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003838
3839 // Workaround: If routing to an non existing usb device, fail gracefully
3840 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003841 int card;
3842 if (audio_is_usb_in_device(val) &&
3843 (card = get_alive_usb_card(parms)) >= 0) {
3844
3845 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003846 status = -ENOSYS;
3847 } else {
3848
3849 in->device = val;
3850 /* If recording is in progress, change the tx device to new device */
3851 if (!in->standby) {
3852 ALOGV("update input routing change");
3853 // inform adm before actual routing to prevent glitches.
3854 if (adev->adm_on_routing_change) {
3855 adev->adm_on_routing_change(adev->adm_data,
3856 in->capture_handle);
3857 }
3858 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003859 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003860 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 }
3862 }
3863
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003865 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866
3867 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003868 ALOGV("%s: exit: status(%d)", __func__, status);
3869 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870}
3871
Haynes Mathew George569b7482017-05-08 14:44:27 -07003872static char* in_get_parameters(const struct audio_stream *stream,
3873 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003874{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003875 struct stream_in *in = (struct stream_in *)stream;
3876 struct str_parms *query = str_parms_create_str(keys);
3877 char *str;
3878 struct str_parms *reply = str_parms_create();
3879 bool replied = false;
3880
3881 ALOGV("%s: enter: keys - %s", __func__, keys);
3882 replied |= stream_get_parameter_channels(query, reply,
3883 &in->supported_channel_masks[0]);
3884 replied |= stream_get_parameter_formats(query, reply,
3885 &in->supported_formats[0]);
3886 replied |= stream_get_parameter_rates(query, reply,
3887 &in->supported_sample_rates[0]);
3888 if (replied) {
3889 str = str_parms_to_str(reply);
3890 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003891 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003892 }
3893 str_parms_destroy(query);
3894 str_parms_destroy(reply);
3895 ALOGV("%s: exit: returns - %s", __func__, str);
3896 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897}
3898
Eric Laurent51f3c662018-04-10 18:21:34 -07003899static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900{
Eric Laurent51f3c662018-04-10 18:21:34 -07003901 struct stream_in *in = (struct stream_in *)stream;
3902 char mixer_ctl_name[128];
3903 struct mixer_ctl *ctl;
3904 int ctl_value;
3905
3906 ALOGV("%s: gain %f", __func__, gain);
3907
3908 if (stream == NULL)
3909 return -EINVAL;
3910
3911 /* in_set_gain() only used to silence MMAP capture for now */
3912 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3913 return -ENOSYS;
3914
3915 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3916
3917 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3918 if (!ctl) {
3919 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3920 __func__, mixer_ctl_name);
3921 return -ENOSYS;
3922 }
3923
3924 if (gain < RECORD_GAIN_MIN)
3925 gain = RECORD_GAIN_MIN;
3926 else if (gain > RECORD_GAIN_MAX)
3927 gain = RECORD_GAIN_MAX;
3928 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3929
3930 mixer_ctl_set_value(ctl, 0, ctl_value);
3931 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932}
3933
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003934static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3935{
3936 if (!stream || !parms)
3937 return;
3938
3939 struct stream_in *in = (struct stream_in *)stream;
3940 struct audio_device *adev = in->dev;
3941
3942 card_status_t status;
3943 int card;
3944 if (parse_snd_card_status(parms, &card, &status) < 0)
3945 return;
3946
3947 pthread_mutex_lock(&adev->lock);
3948 bool valid_cb = (card == adev->snd_card);
3949 pthread_mutex_unlock(&adev->lock);
3950
3951 if (!valid_cb)
3952 return;
3953
3954 lock_input_stream(in);
3955 if (in->card_status != status)
3956 in->card_status = status;
3957 pthread_mutex_unlock(&in->lock);
3958
3959 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3960 use_case_table[in->usecase],
3961 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3962
3963 // a better solution would be to report error back to AF and let
3964 // it put the stream to standby
3965 if (status == CARD_STATUS_OFFLINE)
3966 in_standby(&in->stream.common);
3967
3968 return;
3969}
3970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3972 size_t bytes)
3973{
3974 struct stream_in *in = (struct stream_in *)stream;
3975 struct audio_device *adev = in->dev;
3976 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003977 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003978 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003979
Eric Laurenta1478072015-09-21 17:21:52 -07003980 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003981 const size_t frame_size = audio_stream_in_frame_size(stream);
3982 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003983
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003984 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003985 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003986 /* Read from sound trigger HAL */
3987 audio_extn_sound_trigger_read(in, buffer, bytes);
3988 pthread_mutex_unlock(&in->lock);
3989 return bytes;
3990 }
3991
Eric Laurent0e46adf2016-12-16 12:49:24 -08003992 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3993 ret = -ENOSYS;
3994 goto exit;
3995 }
3996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003998 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004000 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004001 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002 goto exit;
4003 }
4004 in->standby = 0;
4005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006
Andy Hungd13f0d32017-06-12 13:58:37 -07004007 // errors that occur here are read errors.
4008 error_code = ERROR_CODE_READ;
4009
Haynes Mathew George03c40102016-01-29 17:57:48 -08004010 //what's the duration requested by the client?
4011 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4012 in->config.rate;
4013 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004014
Haynes Mathew George03c40102016-01-29 17:57:48 -08004015 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004017 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004018 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004019 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004020 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004021 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004022 if (ret < 0) {
4023 ALOGE("Failed to read w/err %s", strerror(errno));
4024 ret = -errno;
4025 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004026 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4027 if (bytes % 4 == 0) {
4028 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4029 int_buf_stream = buffer;
4030 for (size_t itt=0; itt < bytes/4 ; itt++) {
4031 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004032 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004033 } else {
4034 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4035 ret = -EINVAL;
4036 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004037 }
4038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 }
4040
Haynes Mathew George03c40102016-01-29 17:57:48 -08004041 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043 /*
4044 * Instead of writing zeroes here, we could trust the hardware
4045 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004046 * 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 -08004047 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004048 if (ret == 0 && adev->mic_muted &&
4049 !voice_is_in_call_rec_stream(in) &&
4050 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004052 in->frames_muted += frames;
4053 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054
4055exit:
4056 pthread_mutex_unlock(&in->lock);
4057
4058 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004059 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 in_standby(&in->stream.common);
4061 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004062 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004063 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004064 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004065 }
4066 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004067 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 }
4069 return bytes;
4070}
4071
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004072static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073{
4074 return 0;
4075}
4076
Andy Hung6ebe5962016-01-15 17:46:57 -08004077static int in_get_capture_position(const struct audio_stream_in *stream,
4078 int64_t *frames, int64_t *time)
4079{
4080 if (stream == NULL || frames == NULL || time == NULL) {
4081 return -EINVAL;
4082 }
4083 struct stream_in *in = (struct stream_in *)stream;
4084 int ret = -ENOSYS;
4085
4086 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004087 // note: ST sessions do not close the alsa pcm driver synchronously
4088 // on standby. Therefore, we may return an error even though the
4089 // pcm stream is still opened.
4090 if (in->standby) {
4091 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4092 "%s stream in standby but pcm not NULL for non ST session", __func__);
4093 goto exit;
4094 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004095 if (in->pcm) {
4096 struct timespec timestamp;
4097 unsigned int avail;
4098 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4099 *frames = in->frames_read + avail;
4100 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4101 ret = 0;
4102 }
4103 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004104exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004105 pthread_mutex_unlock(&in->lock);
4106 return ret;
4107}
4108
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004109static int add_remove_audio_effect(const struct audio_stream *stream,
4110 effect_handle_t effect,
4111 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004113 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004114 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004115 int status = 0;
4116 effect_descriptor_t desc;
4117
4118 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004119 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4120
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004121 if (status != 0)
4122 return status;
4123
Eric Laurenta1478072015-09-21 17:21:52 -07004124 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004125 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004126 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004127 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004128 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004129 in->enable_aec != enable &&
4130 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4131 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004132 if (!enable)
4133 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004134 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4135 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4136 adev->enable_voicerx = enable;
4137 struct audio_usecase *usecase;
4138 struct listnode *node;
4139 list_for_each(node, &adev->usecase_list) {
4140 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004141 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004142 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004143 }
4144 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004145 if (!in->standby
4146 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004147 select_devices(in->dev, in->usecase);
4148 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004149 if (in->enable_ns != enable &&
4150 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4151 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004152 if (!in->standby) {
4153 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4154 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4155 select_devices(in->dev, in->usecase);
4156 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004157 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004158 pthread_mutex_unlock(&in->dev->lock);
4159 pthread_mutex_unlock(&in->lock);
4160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 return 0;
4162}
4163
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004164static int in_add_audio_effect(const struct audio_stream *stream,
4165 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166{
Eric Laurent994a6932013-07-17 11:51:42 -07004167 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004168 return add_remove_audio_effect(stream, effect, true);
4169}
4170
4171static int in_remove_audio_effect(const struct audio_stream *stream,
4172 effect_handle_t effect)
4173{
Eric Laurent994a6932013-07-17 11:51:42 -07004174 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004175 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004176}
4177
Eric Laurent0e46adf2016-12-16 12:49:24 -08004178static int in_stop(const struct audio_stream_in* stream)
4179{
4180 struct stream_in *in = (struct stream_in *)stream;
4181 struct audio_device *adev = in->dev;
4182
4183 int ret = -ENOSYS;
4184 ALOGV("%s", __func__);
4185 pthread_mutex_lock(&adev->lock);
4186 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4187 in->capture_started && in->pcm != NULL) {
4188 pcm_stop(in->pcm);
4189 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004190 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004191 }
4192 pthread_mutex_unlock(&adev->lock);
4193 return ret;
4194}
4195
4196static int in_start(const struct audio_stream_in* stream)
4197{
4198 struct stream_in *in = (struct stream_in *)stream;
4199 struct audio_device *adev = in->dev;
4200 int ret = -ENOSYS;
4201
4202 ALOGV("%s in %p", __func__, in);
4203 pthread_mutex_lock(&adev->lock);
4204 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4205 !in->capture_started && in->pcm != NULL) {
4206 if (!in->capture_started) {
4207 ret = start_input_stream(in);
4208 if (ret == 0) {
4209 in->capture_started = true;
4210 }
4211 }
4212 }
4213 pthread_mutex_unlock(&adev->lock);
4214 return ret;
4215}
4216
4217static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4218 int32_t min_size_frames,
4219 struct audio_mmap_buffer_info *info)
4220{
4221 struct stream_in *in = (struct stream_in *)stream;
4222 struct audio_device *adev = in->dev;
4223 int ret = 0;
4224 unsigned int offset1;
4225 unsigned int frames1;
4226 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004227 uint32_t mmap_size;
4228 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004229
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004230 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004231 pthread_mutex_lock(&adev->lock);
4232 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004233
Eric Laurent0e46adf2016-12-16 12:49:24 -08004234 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004235 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004236 ret = -EINVAL;
4237 goto exit;
4238 }
4239 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004240 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004241 ALOGV("%s in %p", __func__, in);
4242 ret = -ENOSYS;
4243 goto exit;
4244 }
4245 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4246 if (in->pcm_device_id < 0) {
4247 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4248 __func__, in->pcm_device_id, in->usecase);
4249 ret = -EINVAL;
4250 goto exit;
4251 }
Phil Burkbc991042017-02-24 08:06:44 -08004252
4253 adjust_mmap_period_count(&in->config, min_size_frames);
4254
Eric Laurent0e46adf2016-12-16 12:49:24 -08004255 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4256 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4257 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4258 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4259 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4260 step = "open";
4261 ret = -ENODEV;
4262 goto exit;
4263 }
4264
4265 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4266 if (ret < 0) {
4267 step = "begin";
4268 goto exit;
4269 }
4270 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004271 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004272 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004273 ret = platform_get_mmap_data_fd(adev->platform,
4274 in->pcm_device_id, 1 /*capture*/,
4275 &info->shared_memory_fd,
4276 &mmap_size);
4277 if (ret < 0) {
4278 // Fall back to non exclusive mode
4279 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4280 } else {
4281 if (mmap_size < buffer_size) {
4282 step = "mmap";
4283 goto exit;
4284 }
4285 // FIXME: indicate exclusive mode support by returning a negative buffer size
4286 info->buffer_size_frames *= -1;
4287 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004288
Haynes Mathew George96483a22017-03-28 14:52:47 -07004289 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004290
4291 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4292 if (ret < 0) {
4293 step = "commit";
4294 goto exit;
4295 }
4296
Phil Burkbc991042017-02-24 08:06:44 -08004297 in->standby = false;
4298 ret = 0;
4299
Eric Laurent0e46adf2016-12-16 12:49:24 -08004300 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4301 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004302
4303exit:
4304 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004305 if (in->pcm == NULL) {
4306 ALOGE("%s: %s - %d", __func__, step, ret);
4307 } else {
4308 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004309 pcm_close(in->pcm);
4310 in->pcm = NULL;
4311 }
4312 }
4313 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004314 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004315 return ret;
4316}
4317
4318static int in_get_mmap_position(const struct audio_stream_in *stream,
4319 struct audio_mmap_position *position)
4320{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004321 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004322 struct stream_in *in = (struct stream_in *)stream;
4323 ALOGVV("%s", __func__);
4324 if (position == NULL) {
4325 return -EINVAL;
4326 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004327 lock_input_stream(in);
4328 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4329 in->pcm == NULL) {
4330 ret = -ENOSYS;
4331 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004332 }
4333 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004334 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004335 if (ret < 0) {
4336 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004337 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004338 }
Andy Hungfc044e12017-03-20 09:24:22 -07004339 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004340exit:
4341 pthread_mutex_unlock(&in->lock);
4342 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004343}
4344
jiabin8962a4d2018-03-19 18:21:24 -07004345static int in_get_active_microphones(const struct audio_stream_in *stream,
4346 struct audio_microphone_characteristic_t *mic_array,
4347 size_t *mic_count) {
4348 struct stream_in *in = (struct stream_in *)stream;
4349 struct audio_device *adev = in->dev;
4350 ALOGVV("%s", __func__);
4351
4352 lock_input_stream(in);
4353 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004354 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004355 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004356 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004357 pthread_mutex_unlock(&adev->lock);
4358 pthread_mutex_unlock(&in->lock);
4359
4360 return ret;
4361}
4362
4363static int adev_get_microphones(const struct audio_hw_device *dev,
4364 struct audio_microphone_characteristic_t *mic_array,
4365 size_t *mic_count) {
4366 struct audio_device *adev = (struct audio_device *)dev;
4367 ALOGVV("%s", __func__);
4368
4369 pthread_mutex_lock(&adev->lock);
4370 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4371 pthread_mutex_unlock(&adev->lock);
4372
4373 return ret;
4374}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004375
Paul McLean57530d52018-12-17 08:24:21 -07004376static int in_set_microphone_direction(const struct audio_stream_in *stream,
4377 audio_microphone_direction_t dir) {
4378 (void)stream;
4379 (void)dir;
4380 ALOGVV("%s", __func__);
4381 return -ENOSYS;
4382}
4383
4384static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4385 (void)stream;
4386 (void)zoom;
4387 ALOGVV("%s", __func__);
4388 return -ENOSYS;
4389}
4390
juyuchenba338cd2019-01-21 11:57:17 +08004391static void in_update_sink_metadata(struct audio_stream_in *stream,
4392 const struct sink_metadata *sink_metadata) {
4393
4394 if (stream == NULL
4395 || sink_metadata == NULL
4396 || sink_metadata->tracks == NULL) {
4397 return;
4398 }
4399
4400 int error = 0;
4401 struct stream_in *in = (struct stream_in *)stream;
4402 struct audio_device *adev = in->dev;
4403 audio_devices_t device = AUDIO_DEVICE_NONE;
4404
4405 if (sink_metadata->track_count != 0)
4406 device = sink_metadata->tracks->dest_device;
4407
4408 lock_input_stream(in);
4409 pthread_mutex_lock(&adev->lock);
4410 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4411
4412 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4413 && device != AUDIO_DEVICE_NONE
4414 && adev->voice_tx_output != NULL) {
4415 /* Use the rx device from afe-proxy record to route voice call because
4416 there is no routing if tx device is on primary hal and rx device
4417 is on other hal during voice call. */
4418 adev->voice_tx_output->devices = device;
4419
4420 if (!voice_is_call_state_active(adev)) {
4421 if (adev->mode == AUDIO_MODE_IN_CALL) {
4422 adev->current_call_output = adev->voice_tx_output;
4423 error = voice_start_call(adev);
4424 if (error != 0)
4425 ALOGE("%s: start voice call failed %d", __func__, error);
4426 }
4427 } else {
4428 adev->current_call_output = adev->voice_tx_output;
4429 voice_update_devices_for_all_voice_usecases(adev);
4430 }
4431 }
4432
4433 pthread_mutex_unlock(&adev->lock);
4434 pthread_mutex_unlock(&in->lock);
4435}
4436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437static int adev_open_output_stream(struct audio_hw_device *dev,
4438 audio_io_handle_t handle,
4439 audio_devices_t devices,
4440 audio_output_flags_t flags,
4441 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004442 struct audio_stream_out **stream_out,
4443 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444{
4445 struct audio_device *adev = (struct audio_device *)dev;
4446 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004447 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004448 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4449 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4450 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451
Andy Hungd9653bd2017-08-01 19:31:39 -07004452 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4453 return -ENOSYS;
4454 }
4455
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004456 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4457 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004458 *stream_out = NULL;
4459 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4460
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004461 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4462
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463 if (devices == AUDIO_DEVICE_NONE)
4464 devices = AUDIO_DEVICE_OUT_SPEAKER;
4465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004466 out->flags = flags;
4467 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004468 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004469 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004470 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004471
4472 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004473 if ((is_hdmi || is_usb_dev) &&
4474 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4475 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4476 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004477 audio_format_t req_format = config->format;
4478 audio_channel_mask_t req_channel_mask = config->channel_mask;
4479 uint32_t req_sample_rate = config->sample_rate;
4480
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004481 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004482 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004483 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004484 if (config->sample_rate == 0)
4485 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004486 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004487 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4488 if (config->format == AUDIO_FORMAT_DEFAULT)
4489 config->format = AUDIO_FORMAT_PCM_16_BIT;
4490 } else if (is_usb_dev) {
4491 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4492 &config->format,
4493 &out->supported_formats[0],
4494 MAX_SUPPORTED_FORMATS,
4495 &config->channel_mask,
4496 &out->supported_channel_masks[0],
4497 MAX_SUPPORTED_CHANNEL_MASKS,
4498 &config->sample_rate,
4499 &out->supported_sample_rates[0],
4500 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004501 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004502 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004503 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004504 if (ret != 0) {
4505 // For MMAP NO IRQ, allow conversions in ADSP
4506 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4507 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004508
Eric Laurentab805ee2018-03-30 12:20:38 -07004509 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4510 config->sample_rate = req_sample_rate;
4511 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4512 config->channel_mask = req_channel_mask;
4513 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4514 config->format = req_format;
4515 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004516
Haynes Mathew George569b7482017-05-08 14:44:27 -07004517 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004518 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004519 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004520 if (is_hdmi) {
4521 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4522 out->config = pcm_config_hdmi_multi;
4523 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4524 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4525 out->config = pcm_config_mmap_playback;
4526 out->stream.start = out_start;
4527 out->stream.stop = out_stop;
4528 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4529 out->stream.get_mmap_position = out_get_mmap_position;
4530 } else {
4531 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4532 out->config = pcm_config_hifi;
4533 }
4534
4535 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004536 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004537 if (is_hdmi) {
4538 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4539 audio_bytes_per_sample(out->format));
4540 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004541 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004542 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004543 pthread_mutex_lock(&adev->lock);
4544 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4545 pthread_mutex_unlock(&adev->lock);
4546
4547 // reject offload during card offline to allow
4548 // fallback to s/w paths
4549 if (offline) {
4550 ret = -ENODEV;
4551 goto error_open;
4552 }
4553
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004554 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4555 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4556 ALOGE("%s: Unsupported Offload information", __func__);
4557 ret = -EINVAL;
4558 goto error_open;
4559 }
4560 if (!is_supported_format(config->offload_info.format)) {
4561 ALOGE("%s: Unsupported audio format", __func__);
4562 ret = -EINVAL;
4563 goto error_open;
4564 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004565 out->sample_rate = config->offload_info.sample_rate;
4566 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4567 out->channel_mask = config->offload_info.channel_mask;
4568 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4569 out->channel_mask = config->channel_mask;
4570 else
4571 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4572
4573 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004574
4575 out->compr_config.codec = (struct snd_codec *)
4576 calloc(1, sizeof(struct snd_codec));
4577
4578 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004579
4580 out->stream.set_callback = out_set_callback;
4581 out->stream.pause = out_pause;
4582 out->stream.resume = out_resume;
4583 out->stream.drain = out_drain;
4584 out->stream.flush = out_flush;
4585
4586 out->compr_config.codec->id =
4587 get_snd_codec_id(config->offload_info.format);
4588 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4589 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004590 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004591 out->compr_config.codec->bit_rate =
4592 config->offload_info.bit_rate;
4593 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004594 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004595 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4596
4597 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4598 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004599
4600 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004601 create_offload_callback_thread(out);
4602 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4603 __func__, config->offload_info.version,
4604 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004605 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4606 switch (config->sample_rate) {
4607 case 0:
4608 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4609 break;
4610 case 8000:
4611 case 16000:
4612 case 48000:
4613 out->sample_rate = config->sample_rate;
4614 break;
4615 default:
4616 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4617 config->sample_rate);
4618 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4619 ret = -EINVAL;
4620 goto error_open;
4621 }
4622 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4623 switch (config->channel_mask) {
4624 case AUDIO_CHANNEL_NONE:
4625 case AUDIO_CHANNEL_OUT_STEREO:
4626 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4627 break;
4628 default:
4629 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4630 config->channel_mask);
4631 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4632 ret = -EINVAL;
4633 goto error_open;
4634 }
4635 switch (config->format) {
4636 case AUDIO_FORMAT_DEFAULT:
4637 case AUDIO_FORMAT_PCM_16_BIT:
4638 out->format = AUDIO_FORMAT_PCM_16_BIT;
4639 break;
4640 default:
4641 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4642 config->format);
4643 config->format = AUDIO_FORMAT_PCM_16_BIT;
4644 ret = -EINVAL;
4645 goto error_open;
4646 }
4647
4648 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004649 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004650 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004651 case 0:
4652 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4653 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004654 case 8000:
4655 case 16000:
4656 case 48000:
4657 out->sample_rate = config->sample_rate;
4658 break;
4659 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004660 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4661 config->sample_rate);
4662 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4663 ret = -EINVAL;
4664 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004665 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004666 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4667 switch (config->channel_mask) {
4668 case AUDIO_CHANNEL_NONE:
4669 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4670 break;
4671 case AUDIO_CHANNEL_OUT_STEREO:
4672 out->channel_mask = config->channel_mask;
4673 break;
4674 default:
4675 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4676 config->channel_mask);
4677 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4678 ret = -EINVAL;
4679 break;
4680 }
4681 switch (config->format) {
4682 case AUDIO_FORMAT_DEFAULT:
4683 out->format = AUDIO_FORMAT_PCM_16_BIT;
4684 break;
4685 case AUDIO_FORMAT_PCM_16_BIT:
4686 out->format = config->format;
4687 break;
4688 default:
4689 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4690 config->format);
4691 config->format = AUDIO_FORMAT_PCM_16_BIT;
4692 ret = -EINVAL;
4693 break;
4694 }
4695 if (ret != 0)
4696 goto error_open;
4697
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004698 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4699 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004700 out->config.rate = out->sample_rate;
4701 out->config.channels =
4702 audio_channel_count_from_out_mask(out->channel_mask);
4703 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004704 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004705 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4706 switch (config->sample_rate) {
4707 case 0:
4708 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4709 break;
4710 case 8000:
4711 case 16000:
4712 case 32000:
4713 case 48000:
4714 out->sample_rate = config->sample_rate;
4715 break;
4716 default:
4717 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4718 config->sample_rate);
4719 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4720 ret = -EINVAL;
4721 break;
4722 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004723 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004724 switch (config->channel_mask) {
4725 case AUDIO_CHANNEL_NONE:
4726 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4727 break;
4728 case AUDIO_CHANNEL_OUT_STEREO:
4729 out->channel_mask = config->channel_mask;
4730 break;
4731 default:
4732 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4733 config->channel_mask);
4734 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4735 ret = -EINVAL;
4736 break;
4737 }
4738 switch (config->format) {
4739 case AUDIO_FORMAT_DEFAULT:
4740 out->format = AUDIO_FORMAT_PCM_16_BIT;
4741 break;
4742 case AUDIO_FORMAT_PCM_16_BIT:
4743 out->format = config->format;
4744 break;
4745 default:
4746 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4747 config->format);
4748 config->format = AUDIO_FORMAT_PCM_16_BIT;
4749 ret = -EINVAL;
4750 break;
4751 }
4752 if (ret != 0)
4753 goto error_open;
4754
vivek mehtaa68fea62017-06-08 19:04:02 -07004755 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004756 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4757 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004758 out->config.rate = out->sample_rate;
4759 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004760 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004761 out->sample_rate,
4762 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004763 out->config.channels,
4764 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004765 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004766 out->config.period_size = buffer_size / frame_size;
4767 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4768 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004770 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004771 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4772 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004773 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004774 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4775 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004776 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004777 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004778 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004779 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004780 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004781 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4782 out->config = pcm_config_mmap_playback;
4783 out->stream.start = out_start;
4784 out->stream.stop = out_stop;
4785 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4786 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004787 } else {
4788 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4789 out->config = pcm_config_low_latency;
4790 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004791
4792 if (config->sample_rate == 0) {
4793 out->sample_rate = out->config.rate;
4794 } else {
4795 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004796 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004797 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4798 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4799 } else {
4800 out->channel_mask = config->channel_mask;
4801 }
4802 if (config->format == AUDIO_FORMAT_DEFAULT)
4803 out->format = audio_format_from_pcm_format(out->config.format);
4804 else if (!audio_is_linear_pcm(config->format)) {
4805 config->format = AUDIO_FORMAT_PCM_16_BIT;
4806 ret = -EINVAL;
4807 goto error_open;
4808 } else {
4809 out->format = config->format;
4810 }
4811
4812 out->config.rate = out->sample_rate;
4813 out->config.channels =
4814 audio_channel_count_from_out_mask(out->channel_mask);
4815 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4816 out->config.format = pcm_format_from_audio_format(out->format);
4817 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004819
4820 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4821 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004822 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004823 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4824 __func__, config->sample_rate, config->format, config->channel_mask);
4825 config->sample_rate = out->sample_rate;
4826 config->format = out->format;
4827 config->channel_mask = out->channel_mask;
4828 ret = -EINVAL;
4829 goto error_open;
4830 }
4831
Andy Hung6fcba9c2014-03-18 11:53:32 -07004832 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4833 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004835 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004836 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004837 adev->primary_output = out;
4838 else {
4839 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004840 ret = -EEXIST;
4841 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004842 }
4843 }
4844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845 /* Check if this usecase is already existing */
4846 pthread_mutex_lock(&adev->lock);
4847 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4848 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004849 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004850 ret = -EEXIST;
4851 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004852 }
4853 pthread_mutex_unlock(&adev->lock);
4854
4855 out->stream.common.get_sample_rate = out_get_sample_rate;
4856 out->stream.common.set_sample_rate = out_set_sample_rate;
4857 out->stream.common.get_buffer_size = out_get_buffer_size;
4858 out->stream.common.get_channels = out_get_channels;
4859 out->stream.common.get_format = out_get_format;
4860 out->stream.common.set_format = out_set_format;
4861 out->stream.common.standby = out_standby;
4862 out->stream.common.dump = out_dump;
4863 out->stream.common.set_parameters = out_set_parameters;
4864 out->stream.common.get_parameters = out_get_parameters;
4865 out->stream.common.add_audio_effect = out_add_audio_effect;
4866 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4867 out->stream.get_latency = out_get_latency;
4868 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004869#ifdef NO_AUDIO_OUT
4870 out->stream.write = out_write_for_no_output;
4871#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004872 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004873#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004874 out->stream.get_render_position = out_get_render_position;
4875 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004876 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877
Eric Laurent0e46adf2016-12-16 12:49:24 -08004878 if (out->realtime)
4879 out->af_period_multiplier = af_period_multiplier;
4880 else
4881 out->af_period_multiplier = 1;
4882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004884 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004885 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004887 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004888 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004889 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004891 config->format = out->stream.common.get_format(&out->stream.common);
4892 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4893 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4894
Kevin Rocarda325aa22018-04-03 09:15:52 -07004895 register_format(out->format, out->supported_formats);
4896 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4897 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4898
Andy Hunga452b0a2017-03-15 14:51:15 -07004899 out->error_log = error_log_create(
4900 ERROR_LOG_ENTRIES,
4901 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4902
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004903 /*
4904 By locking output stream before registering, we allow the callback
4905 to update stream's state only after stream's initial state is set to
4906 adev state.
4907 */
4908 lock_output_stream(out);
4909 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4910 pthread_mutex_lock(&adev->lock);
4911 out->card_status = adev->card_status;
4912 pthread_mutex_unlock(&adev->lock);
4913 pthread_mutex_unlock(&out->lock);
4914
vivek mehta4a824772017-06-08 19:05:49 -07004915 stream_app_type_cfg_init(&out->app_type_cfg);
4916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004917 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004918
Eric Laurent994a6932013-07-17 11:51:42 -07004919 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004921
4922error_open:
4923 free(out);
4924 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004925 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004926 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004927}
4928
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004929static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930 struct audio_stream_out *stream)
4931{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004932 struct stream_out *out = (struct stream_out *)stream;
4933 struct audio_device *adev = out->dev;
4934
Eric Laurent994a6932013-07-17 11:51:42 -07004935 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004936
4937 // must deregister from sndmonitor first to prevent races
4938 // between the callback and close_stream
4939 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004941 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4942 destroy_offload_callback_thread(out);
4943
4944 if (out->compr_config.codec != NULL)
4945 free(out->compr_config.codec);
4946 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004947
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004948 out->a2dp_compress_mute = false;
4949
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004950 if (adev->voice_tx_output == out)
4951 adev->voice_tx_output = NULL;
4952
Andy Hunga452b0a2017-03-15 14:51:15 -07004953 error_log_destroy(out->error_log);
4954 out->error_log = NULL;
4955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004956 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004957 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004958 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004960 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004961}
4962
4963static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4964{
4965 struct audio_device *adev = (struct audio_device *)dev;
4966 struct str_parms *parms;
4967 char *str;
4968 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004969 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004971 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004972 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004973
Joe Onorato188b6222016-03-01 11:02:27 -08004974 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004975
4976 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977
4978 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004979 status = voice_set_parameters(adev, parms);
4980 if (status != 0) {
4981 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 }
4983
4984 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4985 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004986 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4988 adev->bluetooth_nrec = true;
4989 else
4990 adev->bluetooth_nrec = false;
4991 }
4992
4993 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4994 if (ret >= 0) {
4995 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4996 adev->screen_off = false;
4997 else
4998 adev->screen_off = true;
4999 }
5000
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005001 ret = str_parms_get_int(parms, "rotation", &val);
5002 if (ret >= 0) {
5003 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005004 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005005 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005006 // FIXME: note that the code below assumes that the speakers are in the correct placement
5007 // relative to the user when the device is rotated 90deg from its default rotation. This
5008 // assumption is device-specific, not platform-specific like this code.
5009 case 270:
5010 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005011 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005012 break;
5013 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005014 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005015 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5016 break;
5017 case 90:
5018 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005019 break;
5020 default:
5021 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005022 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005023 }
Eric Laurent03f09432014-03-25 18:09:11 -07005024 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005025 // check and set swap
5026 // - check if orientation changed and speaker active
5027 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005028 adev->camera_orientation =
5029 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5030#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005031 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005032#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005033 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005034 }
5035
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005036 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5037 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005038 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005039 }
5040
David Linee3fe402017-03-13 10:00:42 -07005041 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5042 if (ret >= 0) {
5043 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005044 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005045 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5046 if (ret >= 0) {
5047 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005048 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005049 }
Eric Laurent99dab492017-06-17 15:19:08 -07005050 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005051 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5052 if (ret >= 0) {
5053 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005054 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005055 }
5056 }
5057 }
5058
5059 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5060 if (ret >= 0) {
5061 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005062 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005063 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5064 if (ret >= 0) {
5065 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005066 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005067 }
Eric Laurent99dab492017-06-17 15:19:08 -07005068 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005069 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5070 if (ret >= 0) {
5071 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005072 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005073 }
5074 }
5075 }
5076
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005077 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005078 audio_extn_ma_set_parameters(adev, parms);
5079
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005080 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5081 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005082 struct audio_usecase *usecase;
5083 struct listnode *node;
5084 list_for_each(node, &adev->usecase_list) {
5085 usecase = node_to_item(node, struct audio_usecase, list);
5086 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005087 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005088 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5089
5090 pthread_mutex_unlock(&adev->lock);
5091 lock_output_stream(usecase->stream.out);
5092 pthread_mutex_lock(&adev->lock);
5093 audio_extn_a2dp_set_handoff_mode(true);
5094 // force device switch to reconfigure encoder
5095 select_devices(adev, usecase->id);
5096 audio_extn_a2dp_set_handoff_mode(false);
5097 pthread_mutex_unlock(&usecase->stream.out->lock);
5098 break;
5099 }
5100 }
5101 }
5102
Eric Laurent5f4ca952018-10-19 17:33:43 -07005103 //FIXME: to be replaced by proper video capture properties API
5104 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5105 if (ret >= 0) {
5106 int camera_facing = CAMERA_FACING_BACK;
5107 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5108 camera_facing = CAMERA_FACING_FRONT;
5109 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5110 camera_facing = CAMERA_FACING_BACK;
5111 else {
5112 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5113 goto done;
5114 }
5115 adev->camera_orientation =
5116 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5117 struct audio_usecase *usecase;
5118 struct listnode *node;
5119 list_for_each(node, &adev->usecase_list) {
5120 usecase = node_to_item(node, struct audio_usecase, list);
5121 struct stream_in *in = usecase->stream.in;
5122 if (usecase->type == PCM_CAPTURE && in != NULL &&
5123 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5124 select_devices(adev, in->usecase);
5125 }
5126 }
5127 }
5128
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005129done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005130 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005131 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005132 ALOGV("%s: exit with code(%d)", __func__, status);
5133 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134}
5135
5136static char* adev_get_parameters(const struct audio_hw_device *dev,
5137 const char *keys)
5138{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005139 struct audio_device *adev = (struct audio_device *)dev;
5140 struct str_parms *reply = str_parms_create();
5141 struct str_parms *query = str_parms_create_str(keys);
5142 char *str;
5143
5144 pthread_mutex_lock(&adev->lock);
5145
5146 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005147 audio_extn_a2dp_get_parameters(query, reply);
5148
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005149 str = str_parms_to_str(reply);
5150 str_parms_destroy(query);
5151 str_parms_destroy(reply);
5152
5153 pthread_mutex_unlock(&adev->lock);
5154 ALOGV("%s: exit: returns - %s", __func__, str);
5155 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005156}
5157
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005158static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159{
5160 return 0;
5161}
5162
Haynes Mathew George5191a852013-09-11 14:19:36 -07005163static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5164{
5165 int ret;
5166 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005167
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005168 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5169
Haynes Mathew George5191a852013-09-11 14:19:36 -07005170 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005171 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005172 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005173
Haynes Mathew George5191a852013-09-11 14:19:36 -07005174 return ret;
5175}
5176
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005177static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178{
5179 return -ENOSYS;
5180}
5181
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005182static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5183 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184{
5185 return -ENOSYS;
5186}
5187
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005188static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005189{
5190 return -ENOSYS;
5191}
5192
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005193static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194{
5195 return -ENOSYS;
5196}
5197
5198static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5199{
5200 struct audio_device *adev = (struct audio_device *)dev;
5201
5202 pthread_mutex_lock(&adev->lock);
5203 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005204 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005205 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005206 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5207 voice_is_in_call(adev)) {
5208 voice_stop_call(adev);
5209 adev->current_call_output = NULL;
5210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005211 }
5212 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005213
5214 audio_extn_extspk_set_mode(adev->extspk, mode);
5215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005216 return 0;
5217}
5218
5219static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5220{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005221 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005222 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223
Eric Laurent2bafff12016-03-17 12:17:23 -07005224 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005225 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005226 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5227 ret = audio_extn_hfp_set_mic_mute(adev, state);
5228 } else {
5229 ret = voice_set_mic_mute(adev, state);
5230 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005231 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005232 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005233
5234 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005235}
5236
5237static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5238{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005239 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 return 0;
5241}
5242
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005243static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005244 const struct audio_config *config)
5245{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005246 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005247
Eric Laurent74b55762017-07-09 17:04:53 -07005248 /* Don't know if USB HIFI in this context so use true to be conservative */
5249 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5250 true /*is_usb_hifi */) != 0)
5251 return 0;
5252
vivek mehtaa68fea62017-06-08 19:04:02 -07005253 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5254 config->sample_rate, config->format,
5255 channel_count,
5256 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005257}
5258
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005259static bool adev_input_allow_hifi_record(struct audio_device *adev,
5260 audio_devices_t devices,
5261 audio_input_flags_t flags,
5262 audio_source_t source) {
5263 const bool allowed = true;
5264
5265 if (!audio_is_usb_in_device(devices))
5266 return !allowed;
5267
5268 switch (flags) {
5269 case AUDIO_INPUT_FLAG_NONE:
5270 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5271 break;
5272 default:
5273 return !allowed;
5274 }
5275
5276 switch (source) {
5277 case AUDIO_SOURCE_DEFAULT:
5278 case AUDIO_SOURCE_MIC:
5279 case AUDIO_SOURCE_UNPROCESSED:
5280 break;
5281 default:
5282 return !allowed;
5283 }
5284
5285 switch (adev->mode) {
5286 case 0:
5287 break;
5288 default:
5289 return !allowed;
5290 }
5291
5292 return allowed;
5293}
5294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005295static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005296 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 audio_devices_t devices,
5298 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005299 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005300 audio_input_flags_t flags,
5301 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005302 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005303{
5304 struct audio_device *adev = (struct audio_device *)dev;
5305 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005306 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005307 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005308 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005309 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005310 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5311 devices,
5312 flags,
5313 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005314 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5315 " sample_rate %u, channel_mask %#x, format %#x",
5316 __func__, flags, is_usb_dev, may_use_hifi_record,
5317 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005318 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005319
Andy Hungd9653bd2017-08-01 19:31:39 -07005320 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5321 return -ENOSYS;
5322 }
5323
Eric Laurent74b55762017-07-09 17:04:53 -07005324 if (!(is_usb_dev && may_use_hifi_record)) {
5325 if (config->sample_rate == 0)
5326 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5327 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5328 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5329 if (config->format == AUDIO_FORMAT_DEFAULT)
5330 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005331
Eric Laurent74b55762017-07-09 17:04:53 -07005332 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5333
5334 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5335 return -EINVAL;
5336 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005337
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005338 if (audio_extn_tfa_98xx_is_supported() &&
5339 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005340 return -EINVAL;
5341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005342 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5343
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005344 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005345 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005347 in->stream.common.get_sample_rate = in_get_sample_rate;
5348 in->stream.common.set_sample_rate = in_set_sample_rate;
5349 in->stream.common.get_buffer_size = in_get_buffer_size;
5350 in->stream.common.get_channels = in_get_channels;
5351 in->stream.common.get_format = in_get_format;
5352 in->stream.common.set_format = in_set_format;
5353 in->stream.common.standby = in_standby;
5354 in->stream.common.dump = in_dump;
5355 in->stream.common.set_parameters = in_set_parameters;
5356 in->stream.common.get_parameters = in_get_parameters;
5357 in->stream.common.add_audio_effect = in_add_audio_effect;
5358 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5359 in->stream.set_gain = in_set_gain;
5360 in->stream.read = in_read;
5361 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005362 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005363 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005364 in->stream.set_microphone_direction = in_set_microphone_direction;
5365 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005366 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367
5368 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005369 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005370 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005372 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005373 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374
Andy Hung88ce1d92018-10-29 18:31:12 -07005375 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005376 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5377 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5378 /* Force channel config requested to mono if incall
5379 record is being requested for only uplink/downlink */
5380 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5381 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5382 ret = -EINVAL;
5383 goto err_open;
5384 }
5385 }
5386
Haynes Mathew George569b7482017-05-08 14:44:27 -07005387 if (is_usb_dev && may_use_hifi_record) {
5388 /* HiFi record selects an appropriate format, channel, rate combo
5389 depending on sink capabilities*/
5390 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5391 &config->format,
5392 &in->supported_formats[0],
5393 MAX_SUPPORTED_FORMATS,
5394 &config->channel_mask,
5395 &in->supported_channel_masks[0],
5396 MAX_SUPPORTED_CHANNEL_MASKS,
5397 &config->sample_rate,
5398 &in->supported_sample_rates[0],
5399 MAX_SUPPORTED_SAMPLE_RATES);
5400 if (ret != 0) {
5401 ret = -EINVAL;
5402 goto err_open;
5403 }
Eric Laurent74b55762017-07-09 17:04:53 -07005404 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005405 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005406 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005407 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5408 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5409 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5410 bool ret_error = false;
5411 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5412 from HAL is 8_24
5413 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5414 8_24 return error indicating supported format is 8_24
5415 *> In case of any other source requesting 24 bit or float return error
5416 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005417
vivek mehta57ff9b52016-04-28 14:13:08 -07005418 on error flinger will retry with supported format passed
5419 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005420 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005421 config->format = AUDIO_FORMAT_PCM_16_BIT;
5422 ret_error = true;
5423 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5424 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5425 ret_error = true;
5426 }
5427
5428 if (ret_error) {
5429 ret = -EINVAL;
5430 goto err_open;
5431 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005432 }
5433
vivek mehta57ff9b52016-04-28 14:13:08 -07005434 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005435 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005437 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005438 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5439 if (config->sample_rate == 0)
5440 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5441 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5442 config->sample_rate != 8000) {
5443 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5444 ret = -EINVAL;
5445 goto err_open;
5446 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005447
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005448 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5449 config->format = AUDIO_FORMAT_PCM_16_BIT;
5450 ret = -EINVAL;
5451 goto err_open;
5452 }
5453
5454 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5455 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005456 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005457 } else if (is_usb_dev && may_use_hifi_record) {
5458 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5459 in->config = pcm_config_audio_capture;
5460 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005461 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5462 config->sample_rate,
5463 config->format,
5464 channel_count,
5465 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005466 in->config.period_size = buffer_size / frame_size;
5467 in->config.rate = config->sample_rate;
5468 in->af_period_multiplier = 1;
5469 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005470 } else {
5471 in->usecase = USECASE_AUDIO_RECORD;
5472 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005473 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005474 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005475#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005476 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005477#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005478 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005479 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005480 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005481 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005482 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5483 config->sample_rate,
5484 config->format,
5485 channel_count,
5486 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005487 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005488 in->config.rate = config->sample_rate;
5489 in->af_period_multiplier = 1;
5490 } else {
5491 // period size is left untouched for rt mode playback
5492 in->config = pcm_config_audio_capture_rt;
5493 in->af_period_multiplier = af_period_multiplier;
5494 }
5495 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5496 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005497 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005498 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5499 in->config = pcm_config_mmap_capture;
5500 in->stream.start = in_start;
5501 in->stream.stop = in_stop;
5502 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5503 in->stream.get_mmap_position = in_get_mmap_position;
5504 in->af_period_multiplier = 1;
5505 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005506 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005507 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005508 (config->sample_rate == 8000 ||
5509 config->sample_rate == 16000 ||
5510 config->sample_rate == 32000 ||
5511 config->sample_rate == 48000) &&
5512 channel_count == 1) {
5513 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5514 in->config = pcm_config_audio_capture;
5515 frame_size = audio_stream_in_frame_size(&in->stream);
5516 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5517 config->sample_rate,
5518 config->format,
5519 channel_count, false /*is_low_latency*/);
5520 in->config.period_size = buffer_size / frame_size;
5521 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5522 in->config.rate = config->sample_rate;
5523 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005524 } else {
5525 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005526 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005527 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5528 config->sample_rate,
5529 config->format,
5530 channel_count,
5531 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005532 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005533 in->config.rate = config->sample_rate;
5534 in->af_period_multiplier = 1;
5535 }
5536 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5537 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005538 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005541 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005542
Kevin Rocarda325aa22018-04-03 09:15:52 -07005543
5544 register_format(in->format, in->supported_formats);
5545 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5546 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5547
Andy Hungd13f0d32017-06-12 13:58:37 -07005548 in->error_log = error_log_create(
5549 ERROR_LOG_ENTRIES,
5550 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5551
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005552 /* This stream could be for sound trigger lab,
5553 get sound trigger pcm if present */
5554 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005556 lock_input_stream(in);
5557 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5558 pthread_mutex_lock(&adev->lock);
5559 in->card_status = adev->card_status;
5560 pthread_mutex_unlock(&adev->lock);
5561 pthread_mutex_unlock(&in->lock);
5562
vivek mehta4a824772017-06-08 19:05:49 -07005563 stream_app_type_cfg_init(&in->app_type_cfg);
5564
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005565 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005566 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005567 return 0;
5568
5569err_open:
5570 free(in);
5571 *stream_in = NULL;
5572 return ret;
5573}
5574
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005575static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005576 struct audio_stream_in *stream)
5577{
Andy Hungd13f0d32017-06-12 13:58:37 -07005578 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005579 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005580
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005581 // must deregister from sndmonitor first to prevent races
5582 // between the callback and close_stream
5583 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005584 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005585
5586 error_log_destroy(in->error_log);
5587 in->error_log = NULL;
5588
Andy Hung0dbb52b2017-08-09 13:51:38 -07005589 pthread_mutex_destroy(&in->pre_lock);
5590 pthread_mutex_destroy(&in->lock);
5591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005592 free(stream);
5593
5594 return;
5595}
5596
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005597static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005598{
5599 return 0;
5600}
5601
Andy Hung31aca912014-03-20 17:14:59 -07005602/* verifies input and output devices and their capabilities.
5603 *
5604 * This verification is required when enabling extended bit-depth or
5605 * sampling rates, as not all qcom products support it.
5606 *
5607 * Suitable for calling only on initialization such as adev_open().
5608 * It fills the audio_device use_case_table[] array.
5609 *
5610 * Has a side-effect that it needs to configure audio routing / devices
5611 * in order to power up the devices and read the device parameters.
5612 * It does not acquire any hw device lock. Should restore the devices
5613 * back to "normal state" upon completion.
5614 */
5615static int adev_verify_devices(struct audio_device *adev)
5616{
5617 /* enumeration is a bit difficult because one really wants to pull
5618 * the use_case, device id, etc from the hidden pcm_device_table[].
5619 * In this case there are the following use cases and device ids.
5620 *
5621 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5622 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005623 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005624 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5625 * [USECASE_AUDIO_RECORD] = {0, 0},
5626 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5627 * [USECASE_VOICE_CALL] = {2, 2},
5628 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005629 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005630 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5631 */
5632
5633 /* should be the usecases enabled in adev_open_input_stream() */
5634 static const int test_in_usecases[] = {
5635 USECASE_AUDIO_RECORD,
5636 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5637 };
5638 /* should be the usecases enabled in adev_open_output_stream()*/
5639 static const int test_out_usecases[] = {
5640 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5641 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5642 };
5643 static const usecase_type_t usecase_type_by_dir[] = {
5644 PCM_PLAYBACK,
5645 PCM_CAPTURE,
5646 };
5647 static const unsigned flags_by_dir[] = {
5648 PCM_OUT,
5649 PCM_IN,
5650 };
5651
5652 size_t i;
5653 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005654 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005655 char info[512]; /* for possible debug info */
5656
5657 for (dir = 0; dir < 2; ++dir) {
5658 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5659 const unsigned flags_dir = flags_by_dir[dir];
5660 const size_t testsize =
5661 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5662 const int *testcases =
5663 dir ? test_in_usecases : test_out_usecases;
5664 const audio_devices_t audio_device =
5665 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5666
5667 for (i = 0; i < testsize; ++i) {
5668 const audio_usecase_t audio_usecase = testcases[i];
5669 int device_id;
5670 snd_device_t snd_device;
5671 struct pcm_params **pparams;
5672 struct stream_out out;
5673 struct stream_in in;
5674 struct audio_usecase uc_info;
5675 int retval;
5676
5677 pparams = &adev->use_case_table[audio_usecase];
5678 pcm_params_free(*pparams); /* can accept null input */
5679 *pparams = NULL;
5680
5681 /* find the device ID for the use case (signed, for error) */
5682 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5683 if (device_id < 0)
5684 continue;
5685
5686 /* prepare structures for device probing */
5687 memset(&uc_info, 0, sizeof(uc_info));
5688 uc_info.id = audio_usecase;
5689 uc_info.type = usecase_type;
5690 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07005691 memset(&in, 0, sizeof(in));
5692 in.device = audio_device;
5693 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5694 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07005695 }
5696 memset(&out, 0, sizeof(out));
5697 out.devices = audio_device; /* only field needed in select_devices */
5698 uc_info.stream.out = &out;
5699 uc_info.devices = audio_device;
5700 uc_info.in_snd_device = SND_DEVICE_NONE;
5701 uc_info.out_snd_device = SND_DEVICE_NONE;
5702 list_add_tail(&adev->usecase_list, &uc_info.list);
5703
5704 /* select device - similar to start_(in/out)put_stream() */
5705 retval = select_devices(adev, audio_usecase);
5706 if (retval >= 0) {
5707 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5708#if LOG_NDEBUG == 0
5709 if (*pparams) {
5710 ALOGV("%s: (%s) card %d device %d", __func__,
5711 dir ? "input" : "output", card_id, device_id);
5712 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005713 } else {
5714 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5715 }
5716#endif
5717 }
5718
5719 /* deselect device - similar to stop_(in/out)put_stream() */
5720 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005721 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005722 /* 2. Disable the rx device */
5723 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005724 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005725 list_remove(&uc_info.list);
5726 }
5727 }
Andy Hung31aca912014-03-20 17:14:59 -07005728 return 0;
5729}
5730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005731static int adev_close(hw_device_t *device)
5732{
Andy Hung31aca912014-03-20 17:14:59 -07005733 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005734 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005735
5736 if (!adev)
5737 return 0;
5738
5739 pthread_mutex_lock(&adev_init_lock);
5740
5741 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005742 audio_extn_snd_mon_unregister_listener(adev);
5743 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08005744 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005745 audio_route_free(adev->audio_route);
5746 free(adev->snd_dev_ref_cnt);
5747 platform_deinit(adev->platform);
5748 audio_extn_extspk_deinit(adev->extspk);
5749 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005750 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005751 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5752 pcm_params_free(adev->use_case_table[i]);
5753 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005754 if (adev->adm_deinit)
5755 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005756 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005757 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005758 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005759
5760 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005762 return 0;
5763}
5764
Glenn Kasten4f993392014-05-14 07:30:48 -07005765/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5766 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5767 * just that it _might_ work.
5768 */
5769static int period_size_is_plausible_for_low_latency(int period_size)
5770{
5771 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005772 case 48:
5773 case 96:
5774 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005775 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005776 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005777 case 240:
5778 case 320:
5779 case 480:
5780 return 1;
5781 default:
5782 return 0;
5783 }
5784}
5785
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005786static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5787{
5788 int card;
5789 card_status_t status;
5790
5791 if (!parms)
5792 return;
5793
5794 if (parse_snd_card_status(parms, &card, &status) < 0)
5795 return;
5796
5797 pthread_mutex_lock(&adev->lock);
5798 bool valid_cb = (card == adev->snd_card);
5799 if (valid_cb) {
5800 if (adev->card_status != status) {
5801 adev->card_status = status;
5802 platform_snd_card_update(adev->platform, status);
5803 }
5804 }
5805 pthread_mutex_unlock(&adev->lock);
5806 return;
5807}
5808
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005809/* out and adev lock held */
5810static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5811{
5812 struct audio_usecase *uc_info;
5813 float left_p;
5814 float right_p;
5815 audio_devices_t devices;
5816
5817 uc_info = get_usecase_from_list(adev, out->usecase);
5818 if (uc_info == NULL) {
5819 ALOGE("%s: Could not find the usecase (%d) in the list",
5820 __func__, out->usecase);
5821 return -EINVAL;
5822 }
5823
5824 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5825 out->usecase, use_case_table[out->usecase]);
5826
5827 if (restore) {
5828 // restore A2DP device for active usecases and unmute if required
5829 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5830 !is_a2dp_device(uc_info->out_snd_device)) {
5831 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5832 select_devices(adev, uc_info->id);
5833 pthread_mutex_lock(&out->compr_mute_lock);
5834 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5835 (out->a2dp_compress_mute)) {
5836 out->a2dp_compress_mute = false;
5837 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5838 }
5839 pthread_mutex_unlock(&out->compr_mute_lock);
5840 }
5841 } else {
5842 // mute compress stream if suspended
5843 pthread_mutex_lock(&out->compr_mute_lock);
5844 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5845 (!out->a2dp_compress_mute)) {
5846 if (!out->standby) {
5847 ALOGD("%s: selecting speaker and muting stream", __func__);
5848 devices = out->devices;
5849 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5850 left_p = out->volume_l;
5851 right_p = out->volume_r;
5852 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5853 compress_pause(out->compr);
5854 set_compr_volume(&out->stream, 0.0f, 0.0f);
5855 out->a2dp_compress_mute = true;
5856 select_devices(adev, out->usecase);
5857 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5858 compress_resume(out->compr);
5859 out->devices = devices;
5860 out->volume_l = left_p;
5861 out->volume_r = right_p;
5862 }
5863 }
5864 pthread_mutex_unlock(&out->compr_mute_lock);
5865 }
5866 ALOGV("%s: exit", __func__);
5867 return 0;
5868}
5869
5870int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5871{
5872 int ret = 0;
5873
5874 lock_output_stream(out);
5875 pthread_mutex_lock(&adev->lock);
5876
5877 ret = check_a2dp_restore_l(adev, out, restore);
5878
5879 pthread_mutex_unlock(&adev->lock);
5880 pthread_mutex_unlock(&out->lock);
5881 return ret;
5882}
5883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005884static int adev_open(const hw_module_t *module, const char *name,
5885 hw_device_t **device)
5886{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005887 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005888
Eric Laurent2bafff12016-03-17 12:17:23 -07005889 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005891 pthread_mutex_lock(&adev_init_lock);
5892 if (audio_device_ref_count != 0) {
5893 *device = &adev->device.common;
5894 audio_device_ref_count++;
5895 ALOGV("%s: returning existing instance of adev", __func__);
5896 ALOGV("%s: exit", __func__);
5897 pthread_mutex_unlock(&adev_init_lock);
5898 return 0;
5899 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900 adev = calloc(1, sizeof(struct audio_device));
5901
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005902 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5905 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5906 adev->device.common.module = (struct hw_module_t *)module;
5907 adev->device.common.close = adev_close;
5908
5909 adev->device.init_check = adev_init_check;
5910 adev->device.set_voice_volume = adev_set_voice_volume;
5911 adev->device.set_master_volume = adev_set_master_volume;
5912 adev->device.get_master_volume = adev_get_master_volume;
5913 adev->device.set_master_mute = adev_set_master_mute;
5914 adev->device.get_master_mute = adev_get_master_mute;
5915 adev->device.set_mode = adev_set_mode;
5916 adev->device.set_mic_mute = adev_set_mic_mute;
5917 adev->device.get_mic_mute = adev_get_mic_mute;
5918 adev->device.set_parameters = adev_set_parameters;
5919 adev->device.get_parameters = adev_get_parameters;
5920 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5921 adev->device.open_output_stream = adev_open_output_stream;
5922 adev->device.close_output_stream = adev_close_output_stream;
5923 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005925 adev->device.close_input_stream = adev_close_input_stream;
5926 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005927 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005928
5929 /* Set the default route before the PCM stream is opened */
5930 pthread_mutex_lock(&adev->lock);
5931 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005932 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005934 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005935 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005936 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005937 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005938 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 pthread_mutex_unlock(&adev->lock);
5940
5941 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005942 adev->platform = platform_init(adev);
5943 if (!adev->platform) {
5944 free(adev->snd_dev_ref_cnt);
5945 free(adev);
5946 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5947 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005948 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005949 return -EINVAL;
5950 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005951 adev->extspk = audio_extn_extspk_init(adev);
5952
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005953 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5954 if (adev->visualizer_lib == NULL) {
5955 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5956 } else {
5957 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5958 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07005959 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005960 "visualizer_hal_start_output");
5961 adev->visualizer_stop_output =
5962 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5963 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005964 }
5965
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005966 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5967 if (adev->offload_effects_lib == NULL) {
5968 ALOGW("%s: DLOPEN failed for %s", __func__,
5969 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5970 } else {
5971 ALOGV("%s: DLOPEN successful for %s", __func__,
5972 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5973 adev->offload_effects_start_output =
5974 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5975 "offload_effects_bundle_hal_start_output");
5976 adev->offload_effects_stop_output =
5977 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5978 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005979 }
5980
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005981 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5982 if (adev->adm_lib == NULL) {
5983 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5984 } else {
5985 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5986 adev->adm_init = (adm_init_t)
5987 dlsym(adev->adm_lib, "adm_init");
5988 adev->adm_deinit = (adm_deinit_t)
5989 dlsym(adev->adm_lib, "adm_deinit");
5990 adev->adm_register_input_stream = (adm_register_input_stream_t)
5991 dlsym(adev->adm_lib, "adm_register_input_stream");
5992 adev->adm_register_output_stream = (adm_register_output_stream_t)
5993 dlsym(adev->adm_lib, "adm_register_output_stream");
5994 adev->adm_deregister_stream = (adm_deregister_stream_t)
5995 dlsym(adev->adm_lib, "adm_deregister_stream");
5996 adev->adm_request_focus = (adm_request_focus_t)
5997 dlsym(adev->adm_lib, "adm_request_focus");
5998 adev->adm_abandon_focus = (adm_abandon_focus_t)
5999 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006000 adev->adm_set_config = (adm_set_config_t)
6001 dlsym(adev->adm_lib, "adm_set_config");
6002 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6003 dlsym(adev->adm_lib, "adm_request_focus_v2");
6004 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6005 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6006 adev->adm_on_routing_change = (adm_on_routing_change_t)
6007 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006008 }
6009
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006010 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006011 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006013 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006014
Andy Hung31aca912014-03-20 17:14:59 -07006015 if (k_enable_extended_precision)
6016 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006017
Glenn Kasten4f993392014-05-14 07:30:48 -07006018 char value[PROPERTY_VALUE_MAX];
6019 int trial;
6020 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6021 trial = atoi(value);
6022 if (period_size_is_plausible_for_low_latency(trial)) {
6023 pcm_config_low_latency.period_size = trial;
6024 pcm_config_low_latency.start_threshold = trial / 4;
6025 pcm_config_low_latency.avail_min = trial / 4;
6026 configured_low_latency_capture_period_size = trial;
6027 }
6028 }
6029 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6030 trial = atoi(value);
6031 if (period_size_is_plausible_for_low_latency(trial)) {
6032 configured_low_latency_capture_period_size = trial;
6033 }
6034 }
6035
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006036 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6037
Eric Laurent5f4ca952018-10-19 17:33:43 -07006038 adev->camera_orientation = CAMERA_DEFAULT;
6039
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006040 // commented as full set of app type cfg is sent from platform
6041 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006042 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006043
6044 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6045 af_period_multiplier = atoi(value);
6046 if (af_period_multiplier < 0) {
6047 af_period_multiplier = 2;
6048 } else if (af_period_multiplier > 4) {
6049 af_period_multiplier = 4;
6050 }
6051 ALOGV("new period_multiplier = %d", af_period_multiplier);
6052 }
6053
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006054 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006055 audio_extn_ma_init(adev->platform);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006056
vivek mehta1a9b7c02015-06-25 11:49:38 -07006057 pthread_mutex_unlock(&adev_init_lock);
6058
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006059 if (adev->adm_init)
6060 adev->adm_data = adev->adm_init();
6061
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006062 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006063 audio_extn_snd_mon_init();
6064 pthread_mutex_lock(&adev->lock);
6065 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6066 adev->card_status = CARD_STATUS_ONLINE;
6067 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006068 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006069
Eric Laurent2bafff12016-03-17 12:17:23 -07006070 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006071 return 0;
6072}
6073
6074static struct hw_module_methods_t hal_module_methods = {
6075 .open = adev_open,
6076};
6077
6078struct audio_module HAL_MODULE_INFO_SYM = {
6079 .common = {
6080 .tag = HARDWARE_MODULE_TAG,
6081 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6082 .hal_api_version = HARDWARE_HAL_API_VERSION,
6083 .id = AUDIO_HARDWARE_MODULE_ID,
6084 .name = "QCOM Audio HAL",
6085 .author = "Code Aurora Forum",
6086 .methods = &hal_module_methods,
6087 },
6088};