blob: 5a1ae4d9e454a184e696c283ec1cc21cb73848f1 [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>
Andy Hung572633e2019-02-19 11:58:24 -080043#include <utils/Timers.h> // systemTime
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Suren Baghdasaryan7f924c22018-12-21 15:07:18 -080047#include <processgroup/sched_policy.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070048#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080049#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include <audio_effects/effect_aec.h>
51#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070052#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080055#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070056#include "platform_api.h"
57#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070058#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080059
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080061#include "audio_extn/tfa_98xx.h"
jasmine cha270b7762018-03-30 15:41:33 +080062#include "audio_extn/maxxaudio.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070063
Eric Laurent397db572016-05-11 11:31:47 -070064/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
65 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070066#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070067// 2 buffers causes problems with high bitrate files
68#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070069/* ToDo: Check and update a proper value in msec */
70#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070071/* treat as unsigned Q1.13 */
72#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070073#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070074
75/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070076#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070077
Eric Laurent51f3c662018-04-10 18:21:34 -070078#define RECORD_GAIN_MIN 0.0f
79#define RECORD_GAIN_MAX 1.0f
80#define RECORD_VOLUME_CTL_MAX 0x2000
81
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070082#define PROXY_OPEN_RETRY_COUNT 100
83#define PROXY_OPEN_WAIT_TIME 20
84
vivek mehtadae44712015-07-27 14:13:18 -070085#define MIN_CHANNEL_COUNT 1
86#define DEFAULT_CHANNEL_COUNT 2
87
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
89#define MAX_CHANNEL_COUNT 1
90#else
vivek mehtadae44712015-07-27 14:13:18 -070091#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
92#define XSTR(x) STR(x)
93#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070094#endif
Eric Laurent74b55762017-07-09 17:04:53 -070095#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070096
Haynes Mathew George03c40102016-01-29 17:57:48 -080097#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
98
Glenn Kasten4f993392014-05-14 07:30:48 -070099static unsigned int configured_low_latency_capture_period_size =
100 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
101
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
103#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800104#define MMAP_PERIOD_COUNT_MIN 32
105#define MMAP_PERIOD_COUNT_MAX 512
106#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800107
Andy Hung31aca912014-03-20 17:14:59 -0700108/* This constant enables extended precision handling.
109 * TODO The flag is off until more testing is done.
110 */
111static const bool k_enable_extended_precision = false;
112
Eric Laurentb23d5282013-05-14 15:27:20 -0700113struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700114 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
117 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
120 .stop_threshold = INT_MAX,
121 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
122};
123
124struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700125 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
128 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
131 .stop_threshold = INT_MAX,
132 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
133};
134
Haynes Mathew George03c40102016-01-29 17:57:48 -0800135static int af_period_multiplier = 4;
136struct pcm_config pcm_config_rt = {
137 .channels = DEFAULT_CHANNEL_COUNT,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = ULL_PERIOD_SIZE, //1 ms
140 .period_count = 512, //=> buffer size is 512ms
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
143 .stop_threshold = INT_MAX,
144 .silence_threshold = 0,
145 .silence_size = 0,
146 .avail_min = ULL_PERIOD_SIZE, //1 ms
147};
148
Eric Laurentb23d5282013-05-14 15:27:20 -0700149struct pcm_config pcm_config_hdmi_multi = {
150 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
151 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
152 .period_size = HDMI_MULTI_PERIOD_SIZE,
153 .period_count = HDMI_MULTI_PERIOD_COUNT,
154 .format = PCM_FORMAT_S16_LE,
155 .start_threshold = 0,
156 .stop_threshold = INT_MAX,
157 .avail_min = 0,
158};
159
Eric Laurent0e46adf2016-12-16 12:49:24 -0800160struct pcm_config pcm_config_mmap_playback = {
161 .channels = DEFAULT_CHANNEL_COUNT,
162 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
163 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800164 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800165 .format = PCM_FORMAT_S16_LE,
166 .start_threshold = MMAP_PERIOD_SIZE*8,
167 .stop_threshold = INT32_MAX,
168 .silence_threshold = 0,
169 .silence_size = 0,
170 .avail_min = MMAP_PERIOD_SIZE, //1 ms
171};
172
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800173struct pcm_config pcm_config_hifi = {
174 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
175 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
176 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
177 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
178 .format = PCM_FORMAT_S24_3LE,
179 .start_threshold = 0,
180 .stop_threshold = INT_MAX,
181 .avail_min = 0,
182};
183
Eric Laurentb23d5282013-05-14 15:27:20 -0700184struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700185 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700186 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
187 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700188 .stop_threshold = INT_MAX,
189 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700190};
191
Haynes Mathew George03c40102016-01-29 17:57:48 -0800192struct pcm_config pcm_config_audio_capture_rt = {
193 .channels = DEFAULT_CHANNEL_COUNT,
194 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
195 .period_size = ULL_PERIOD_SIZE,
196 .period_count = 512,
197 .format = PCM_FORMAT_S16_LE,
198 .start_threshold = 0,
199 .stop_threshold = INT_MAX,
200 .silence_threshold = 0,
201 .silence_size = 0,
202 .avail_min = ULL_PERIOD_SIZE, //1 ms
203};
204
Eric Laurent0e46adf2016-12-16 12:49:24 -0800205struct pcm_config pcm_config_mmap_capture = {
206 .channels = DEFAULT_CHANNEL_COUNT,
207 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
208 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800209 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800210 .format = PCM_FORMAT_S16_LE,
211 .start_threshold = 0,
212 .stop_threshold = INT_MAX,
213 .silence_threshold = 0,
214 .silence_size = 0,
215 .avail_min = MMAP_PERIOD_SIZE, //1 ms
216};
217
vivek mehtaa68fea62017-06-08 19:04:02 -0700218struct pcm_config pcm_config_voip = {
219 .channels = 1,
220 .period_count = 2,
221 .format = PCM_FORMAT_S16_LE,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700226#define AFE_PROXY_CHANNEL_COUNT 2
227#define AFE_PROXY_SAMPLING_RATE 48000
228
jiabinad481a72018-07-23 12:03:17 -0700229#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700230#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
231
232struct pcm_config pcm_config_afe_proxy_playback = {
233 .channels = AFE_PROXY_CHANNEL_COUNT,
234 .rate = AFE_PROXY_SAMPLING_RATE,
235 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
236 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
237 .format = PCM_FORMAT_S16_LE,
238 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
239 .stop_threshold = INT_MAX,
240 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
241};
242
jiabinad481a72018-07-23 12:03:17 -0700243#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700244#define AFE_PROXY_RECORD_PERIOD_COUNT 4
245
246struct pcm_config pcm_config_afe_proxy_record = {
247 .channels = AFE_PROXY_CHANNEL_COUNT,
248 .rate = AFE_PROXY_SAMPLING_RATE,
249 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
250 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
251 .format = PCM_FORMAT_S16_LE,
252 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700253 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700254 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
255};
256
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700257const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700258 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
259 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800260 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700261 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700262 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700263 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800264 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265
Eric Laurentb23d5282013-05-14 15:27:20 -0700266 [USECASE_AUDIO_RECORD] = "audio-record",
267 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800268 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700269 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700270
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800271 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
272 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700273
Eric Laurentb23d5282013-05-14 15:27:20 -0700274 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700275 [USECASE_VOICE2_CALL] = "voice2-call",
276 [USECASE_VOLTE_CALL] = "volte-call",
277 [USECASE_QCHAT_CALL] = "qchat-call",
278 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800279 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
280 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700281
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700282 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
283 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
284
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700285 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
286 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700287
288 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
289 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
290 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
291
vivek mehtaa68fea62017-06-08 19:04:02 -0700292 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
293 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200294
295 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700296
297 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700298};
299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300
301#define STRING_TO_ENUM(string) { #string, string }
302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800303struct string_to_enum {
304 const char *name;
305 uint32_t value;
306};
307
Haynes Mathew George569b7482017-05-08 14:44:27 -0700308static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800309 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
310 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
311 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700312 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700313 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700314 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
315 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
316 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
317 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
318 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
319 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
320 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
321 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
322 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800323};
324
Haynes Mathew George5191a852013-09-11 14:19:36 -0700325static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700326static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700327static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700328static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700329//cache last MBDRC cal step level
330static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700331
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800332static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
333static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
334
Haynes Mathew George03c40102016-01-29 17:57:48 -0800335static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
336 int flags __unused)
337{
338 int dir = 0;
339 switch (uc_id) {
340 case USECASE_AUDIO_RECORD_LOW_LATENCY:
341 dir = 1;
342 case USECASE_AUDIO_PLAYBACK_ULL:
343 break;
344 default:
345 return false;
346 }
347
348 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
349 PCM_PLAYBACK : PCM_CAPTURE);
350 if (adev->adm_is_noirq_avail)
351 return adev->adm_is_noirq_avail(adev->adm_data,
352 adev->snd_card, dev_id, dir);
353 return false;
354}
355
356static void register_out_stream(struct stream_out *out)
357{
358 struct audio_device *adev = out->dev;
359 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
360 return;
361
362 if (!adev->adm_register_output_stream)
363 return;
364
365 adev->adm_register_output_stream(adev->adm_data,
366 out->handle,
367 out->flags);
368
369 if (!adev->adm_set_config)
370 return;
371
372 if (out->realtime) {
373 adev->adm_set_config(adev->adm_data,
374 out->handle,
375 out->pcm, &out->config);
376 }
377}
378
379static void register_in_stream(struct stream_in *in)
380{
381 struct audio_device *adev = in->dev;
382 if (!adev->adm_register_input_stream)
383 return;
384
385 adev->adm_register_input_stream(adev->adm_data,
386 in->capture_handle,
387 in->flags);
388
389 if (!adev->adm_set_config)
390 return;
391
392 if (in->realtime) {
393 adev->adm_set_config(adev->adm_data,
394 in->capture_handle,
395 in->pcm,
396 &in->config);
397 }
398}
399
400static void request_out_focus(struct stream_out *out, long ns)
401{
402 struct audio_device *adev = out->dev;
403
Haynes Mathew George03c40102016-01-29 17:57:48 -0800404 if (adev->adm_request_focus_v2) {
405 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
406 } else if (adev->adm_request_focus) {
407 adev->adm_request_focus(adev->adm_data, out->handle);
408 }
409}
410
411static void request_in_focus(struct stream_in *in, long ns)
412{
413 struct audio_device *adev = in->dev;
414
Haynes Mathew George03c40102016-01-29 17:57:48 -0800415 if (adev->adm_request_focus_v2) {
416 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
417 } else if (adev->adm_request_focus) {
418 adev->adm_request_focus(adev->adm_data, in->capture_handle);
419 }
420}
421
422static void release_out_focus(struct stream_out *out, long ns __unused)
423{
424 struct audio_device *adev = out->dev;
425
426 if (adev->adm_abandon_focus)
427 adev->adm_abandon_focus(adev->adm_data, out->handle);
428}
429
430static void release_in_focus(struct stream_in *in, long ns __unused)
431{
432 struct audio_device *adev = in->dev;
433 if (adev->adm_abandon_focus)
434 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
435}
436
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700437static int parse_snd_card_status(struct str_parms * parms, int * card,
438 card_status_t * status)
439{
440 char value[32]={0};
441 char state[32]={0};
442
443 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
444
445 if (ret < 0)
446 return -1;
447
448 // sscanf should be okay as value is of max length 32.
449 // same as sizeof state.
450 if (sscanf(value, "%d,%s", card, state) < 2)
451 return -1;
452
453 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
454 CARD_STATUS_OFFLINE;
455 return 0;
456}
457
vivek mehta40125092017-08-21 18:48:51 -0700458// always call with adev lock held
459void send_gain_dep_calibration_l() {
460 if (last_known_cal_step >= 0)
461 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
462}
463
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464__attribute__ ((visibility ("default")))
465bool audio_hw_send_gain_dep_calibration(int level) {
466 bool ret_val = false;
467 ALOGV("%s: enter ... ", __func__);
468
469 pthread_mutex_lock(&adev_init_lock);
470
471 if (adev != NULL && adev->platform != NULL) {
472 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700473 last_known_cal_step = level;
474 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700475 pthread_mutex_unlock(&adev->lock);
476 } else {
477 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
478 }
479
480 pthread_mutex_unlock(&adev_init_lock);
481
482 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
483 return ret_val;
484}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700485
jasmine cha270b7762018-03-30 15:41:33 +0800486#ifdef MAXXAUDIO_QDSP_ENABLED
487bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
488{
489 bool ret = false;
490 ALOGV("%s: enter ...", __func__);
491
492 pthread_mutex_lock(&adev_init_lock);
493
494 if (adev != NULL && adev->platform != NULL) {
495 pthread_mutex_lock(&adev->lock);
496 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
497 pthread_mutex_unlock(&adev->lock);
498 }
499
500 pthread_mutex_unlock(&adev_init_lock);
501
502 ALOGV("%s: exit with ret %d", __func__, ret);
503 return ret;
504}
505#else
506#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
507#endif
508
vivek mehtaa8d7c922016-05-25 14:40:44 -0700509__attribute__ ((visibility ("default")))
510int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
511 int table_size) {
512 int ret_val = 0;
513 ALOGV("%s: enter ... ", __func__);
514
515 pthread_mutex_lock(&adev_init_lock);
516 if (adev == NULL) {
517 ALOGW("%s: adev is NULL .... ", __func__);
518 goto done;
519 }
520
521 pthread_mutex_lock(&adev->lock);
522 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
523 pthread_mutex_unlock(&adev->lock);
524done:
525 pthread_mutex_unlock(&adev_init_lock);
526 ALOGV("%s: exit ... ", __func__);
527 return ret_val;
528}
529
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700530static bool is_supported_format(audio_format_t format)
531{
Eric Laurent8251ac82014-07-23 11:00:25 -0700532 switch (format) {
533 case AUDIO_FORMAT_MP3:
534 case AUDIO_FORMAT_AAC_LC:
535 case AUDIO_FORMAT_AAC_HE_V1:
536 case AUDIO_FORMAT_AAC_HE_V2:
537 return true;
538 default:
539 break;
540 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700541 return false;
542}
543
juyuchenbe5c67e2018-08-29 17:19:20 +0800544static bool is_supported_24bits_audiosource(audio_source_t source)
545{
546 switch (source) {
547 case AUDIO_SOURCE_UNPROCESSED:
548#ifdef ENABLED_24BITS_CAMCORDER
549 case AUDIO_SOURCE_CAMCORDER:
550#endif
551 return true;
552 default:
553 break;
554 }
555 return false;
556}
557
Haynes Mathew George03c40102016-01-29 17:57:48 -0800558static inline bool is_mmap_usecase(audio_usecase_t uc_id)
559{
560 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
561 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
562}
563
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700564static int get_snd_codec_id(audio_format_t format)
565{
566 int id = 0;
567
Eric Laurent8251ac82014-07-23 11:00:25 -0700568 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700569 case AUDIO_FORMAT_MP3:
570 id = SND_AUDIOCODEC_MP3;
571 break;
572 case AUDIO_FORMAT_AAC:
573 id = SND_AUDIOCODEC_AAC;
574 break;
575 default:
576 ALOGE("%s: Unsupported audio format", __func__);
577 }
578
579 return id;
580}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800581
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800582static int audio_ssr_status(struct audio_device *adev)
583{
584 int ret = 0;
585 struct mixer_ctl *ctl;
586 const char *mixer_ctl_name = "Audio SSR Status";
587
588 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
589 ret = mixer_ctl_get_value(ctl, 0);
590 ALOGD("%s: value: %d", __func__, ret);
591 return ret;
592}
593
vivek mehta4a824772017-06-08 19:05:49 -0700594static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
595{
596 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
597}
598
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800599static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
600{
601 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
602 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
603 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
604 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
605 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
606 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
607
608}
609
610static bool is_a2dp_device(snd_device_t out_snd_device)
611{
612 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
613}
614
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800615int enable_audio_route(struct audio_device *adev,
616 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800617{
yixuanjiang509f0a72018-09-06 18:37:23 +0800618 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700619 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800620
621 if (usecase == NULL)
622 return -EINVAL;
623
624 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
625
yixuanjiang509f0a72018-09-06 18:37:23 +0800626 if (usecase->type == PCM_CAPTURE)
627 snd_device = usecase->in_snd_device;
628 else
629 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530630 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800631 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700632
633 // we shouldn't truncate mixer_path
634 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
635 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
636 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800637 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700638
yixuanjiang509f0a72018-09-06 18:37:23 +0800639 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700640 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700641 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800643 ALOGV("%s: exit", __func__);
644 return 0;
645}
646
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800647int disable_audio_route(struct audio_device *adev,
648 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800649{
yixuanjiang509f0a72018-09-06 18:37:23 +0800650 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700651 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800652
653 if (usecase == NULL)
654 return -EINVAL;
655
656 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800657 if (usecase->type == PCM_CAPTURE)
658 snd_device = usecase->in_snd_device;
659 else
660 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700661
662 // we shouldn't truncate mixer_path
663 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
664 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
665 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800666 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700667 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700668
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700669 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000670 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800672 ALOGV("%s: exit", __func__);
673 return 0;
674}
675
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800676int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700677 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800678{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700679 int i, num_devices = 0;
680 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800681 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800682 if (snd_device < SND_DEVICE_MIN ||
683 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800684 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800685 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800686 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700687
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700688 platform_send_audio_calibration(adev->platform, snd_device);
689
vivek mehtade4849c2016-03-03 17:23:38 -0800690 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700691 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700692 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800693 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 }
695
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700696 /* due to the possibility of calibration overwrite between listen
697 and audio, notify sound trigger hal before audio calibration is sent */
698 audio_extn_sound_trigger_update_device_status(snd_device,
699 ST_EVENT_SND_DEVICE_BUSY);
700
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 if (audio_extn_spkr_prot_is_enabled())
702 audio_extn_spkr_prot_calib_cancel(adev);
703
zhaoyang yin4211fad2015-06-04 21:13:25 +0800704 audio_extn_dsm_feedback_enable(adev, snd_device, true);
705
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700706 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800707 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800708 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700709 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
710 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700711 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800712 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700713 }
714 if (audio_extn_spkr_prot_start_processing(snd_device)) {
715 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800716 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700717 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700718 } else if (platform_can_split_snd_device(snd_device,
719 &num_devices,
720 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700721 for (i = 0; i < num_devices; i++) {
722 enable_snd_device(adev, new_snd_devices[i]);
723 }
vivek mehtab6506412015-08-07 16:55:17 -0700724 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700725 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800726 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
727 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
728 ALOGE(" %s: Invalid sound device returned", __func__);
729 goto on_error;
730 }
Ed Tam70b5c142016-03-21 19:14:29 -0700731
Eric Laurent2e140aa2016-06-30 17:14:46 -0700732 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700733
734 if (is_a2dp_device(snd_device) &&
735 (audio_extn_a2dp_start_playback() < 0)) {
736 ALOGE("%s: failed to configure A2DP control path", __func__);
737 goto on_error;
738 }
739
vivek mehtade4849c2016-03-03 17:23:38 -0800740 audio_route_apply_and_update_path(adev->audio_route, device_name);
741 }
742on_success:
743 adev->snd_dev_ref_cnt[snd_device]++;
744 ret_val = 0;
745on_error:
746 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800747}
748
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800749int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700750 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700752 int i, num_devices = 0;
753 snd_device_t new_snd_devices[2];
754
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800755 if (snd_device < SND_DEVICE_MIN ||
756 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800757 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800758 return -EINVAL;
759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
761 ALOGE("%s: device ref cnt is already 0", __func__);
762 return -EINVAL;
763 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800764 audio_extn_tfa_98xx_disable_speaker(snd_device);
765
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700766 adev->snd_dev_ref_cnt[snd_device]--;
767 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800768 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800769
770 if (is_a2dp_device(snd_device))
771 audio_extn_a2dp_stop_playback();
772
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700773 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800774 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700775 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700776 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
777 audio_extn_spkr_prot_is_enabled()) {
778 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700779
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700780 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
781 // and does not use speaker swap. As this code causes a problem with device enable ref
782 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700783 // when speaker device is disabled, reset swap.
784 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700785 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700786
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700787 } else if (platform_can_split_snd_device(snd_device,
788 &num_devices,
789 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700790 for (i = 0; i < num_devices; i++) {
791 disable_snd_device(adev, new_snd_devices[i]);
792 }
vivek mehtab6506412015-08-07 16:55:17 -0700793 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700794 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800795 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
796 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
797 ALOGE(" %s: Invalid sound device returned", __func__);
798 return -EINVAL;
799 }
800
Eric Laurent2e140aa2016-06-30 17:14:46 -0700801 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800802 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700803 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700804 audio_extn_sound_trigger_update_device_status(snd_device,
805 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700806 }
vivek mehtab6506412015-08-07 16:55:17 -0700807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808 return 0;
809}
810
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800811#ifdef DYNAMIC_ECNS_ENABLED
812static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
813 struct stream_in *in,
814 struct audio_effect_config effect_config,
815 unsigned int param_value)
816{
817 char mixer_ctl_name[] = "Audio Effect";
818 long set_values[6];
819
820 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
821 if (!ctl) {
822 ALOGE("%s: Could not get mixer ctl - %s",
823 __func__, mixer_ctl_name);
824 return -EINVAL;
825 }
826
827 set_values[0] = 1; //0:Rx 1:Tx
828 set_values[1] = in->app_type_cfg.app_type;
829 set_values[2] = (long)effect_config.module_id;
830 set_values[3] = (long)effect_config.instance_id;
831 set_values[4] = (long)effect_config.param_id;
832 set_values[5] = param_value;
833
834 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
835
836 return 0;
837
838}
839
840static int update_effect_param_ecns(struct audio_usecase *usecase,
841 unsigned int module_id, int effect_type,
842 unsigned int *param_value)
843{
844 int ret = 0;
845 struct audio_effect_config other_effect_config;
846 struct stream_in *in = NULL;
847
848 if (!usecase)
849 return -EINVAL;
850
851 in = usecase->stream.in;
852
853 /* Get the effect config data of the other effect */
854 ret = platform_get_effect_config_data(usecase->in_snd_device,
855 &other_effect_config,
856 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
857 if (ret < 0) {
858 ALOGE("%s Failed to get effect params %d", __func__, ret);
859 return ret;
860 }
861
862 if (module_id == other_effect_config.module_id) {
863 //Same module id for AEC/NS. Values need to be combined
864 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
865 ((effect_type == EFFECT_NS) && (in->enable_aec)))
866 *param_value |= other_effect_config.param_value;
867 }
868
869 return ret;
870}
871
872static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
873 int effect_type, bool enable)
874{
875 struct audio_effect_config effect_config;
876 struct audio_usecase *usecase = NULL;
877 int ret = 0;
878 unsigned int param_value = 0;
879
880 if (!in) {
881 ALOGE("%s: Invalid input stream", __func__);
882 return -EINVAL;
883 }
884
885 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
886
887 usecase = get_usecase_from_list(adev, in->usecase);
888
889 ret = platform_get_effect_config_data(usecase->in_snd_device,
890 &effect_config, effect_type);
891 if (ret < 0) {
892 ALOGE("%s Failed to get module id %d", __func__, ret);
893 return ret;
894 }
895 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
896 __func__, effect_config.module_id, in->app_type_cfg.app_type,
897 usecase->id, usecase->in_snd_device);
898
899 if (enable)
900 param_value = effect_config.param_value;
901
902 /*Special handling for AEC & NS effects Param values need to be
903 updated if module ids are same*/
904
905 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
906 ret = update_effect_param_ecns(usecase, effect_config.module_id,
907 effect_type, &param_value);
908 if (ret < 0)
909 return ret;
910 }
911
912 ret = send_effect_enable_disable_mixer_ctl(adev, in,
913 effect_config, param_value);
914
915 return ret;
916}
917
918static int check_and_enable_effect(struct audio_device *adev)
919{
920 int ret = 0;
921
922 struct listnode *node;
923 struct stream_in *in = NULL;
924
925 list_for_each(node, &adev->usecase_list)
926 {
927 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
928 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
929 in = usecase->stream.in;
930
931 if (in->standby)
932 continue;
933
934 if (in->enable_aec) {
935 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
936 }
937
938 if (in->enable_ns &&
939 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
940 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
941 }
942 }
943 }
944
945 return ret;
946}
947#else
948#define enable_disable_effect(w, x, y, z) -ENOSYS
949#define check_and_enable_effect(x) -ENOSYS
950#endif
951
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700952/*
953 legend:
954 uc - existing usecase
955 new_uc - new usecase
956 d1, d11, d2 - SND_DEVICE enums
957 a1, a2 - corresponding ANDROID device enums
958 B, B1, B2 - backend strings
959
960case 1
961 uc->dev d1 (a1) B1
962 new_uc->dev d1 (a1), d2 (a2) B1, B2
963
964 resolution: disable and enable uc->dev on d1
965
966case 2
967 uc->dev d1 (a1) B1
968 new_uc->dev d11 (a1) B1
969
970 resolution: need to switch uc since d1 and d11 are related
971 (e.g. speaker and voice-speaker)
972 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
973
974case 3
975 uc->dev d1 (a1) B1
976 new_uc->dev d2 (a2) B2
977
978 resolution: no need to switch uc
979
980case 4
981 uc->dev d1 (a1) B
982 new_uc->dev d2 (a2) B
983
984 resolution: disable enable uc-dev on d2 since backends match
985 we cannot enable two streams on two different devices if they
986 share the same backend. e.g. if offload is on speaker device using
987 QUAD_MI2S backend and a low-latency stream is started on voice-handset
988 using the same backend, offload must also be switched to voice-handset.
989
990case 5
991 uc->dev d1 (a1) B
992 new_uc->dev d1 (a1), d2 (a2) B
993
994 resolution: disable enable uc-dev on d2 since backends match
995 we cannot enable two streams on two different devices if they
996 share the same backend.
997
998case 6
999 uc->dev d1 a1 B1
1000 new_uc->dev d2 a1 B2
1001
1002 resolution: no need to switch
1003
1004case 7
1005
1006 uc->dev d1 (a1), d2 (a2) B1, B2
1007 new_uc->dev d1 B1
1008
1009 resolution: no need to switch
1010
1011*/
1012static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1013 struct audio_usecase *new_uc,
1014 snd_device_t new_snd_device)
1015{
1016 audio_devices_t a1 = uc->stream.out->devices;
1017 audio_devices_t a2 = new_uc->stream.out->devices;
1018
1019 snd_device_t d1 = uc->out_snd_device;
1020 snd_device_t d2 = new_snd_device;
1021
1022 // Treat as a special case when a1 and a2 are not disjoint
1023 if ((a1 != a2) && (a1 & a2)) {
1024 snd_device_t d3[2];
1025 int num_devices = 0;
1026 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1027 &num_devices,
1028 d3);
1029 if (ret < 0) {
1030 if (ret != -ENOSYS) {
1031 ALOGW("%s failed to split snd_device %d",
1032 __func__,
1033 popcount(a1) > 1 ? d1 : d2);
1034 }
1035 goto end;
1036 }
1037
1038 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1039 // But if it does happen, we need to give priority to d2 if
1040 // the combo devices active on the existing usecase share a backend.
1041 // This is because we cannot have a usecase active on a combo device
1042 // and a new usecase requests one device in this combo pair.
1043 if (platform_check_backends_match(d3[0], d3[1])) {
1044 return d2; // case 5
1045 } else {
1046 return d1; // case 1
1047 }
1048 } else {
1049 if (platform_check_backends_match(d1, d2)) {
1050 return d2; // case 2, 4
1051 } else {
1052 return d1; // case 6, 3
1053 }
1054 }
1055
1056end:
1057 return d2; // return whatever was calculated before.
1058}
1059
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001060static void check_and_route_playback_usecases(struct audio_device *adev,
1061 struct audio_usecase *uc_info,
1062 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001063{
1064 struct listnode *node;
1065 struct audio_usecase *usecase;
1066 bool switch_device[AUDIO_USECASE_MAX];
1067 int i, num_uc_to_switch = 0;
1068
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001069 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1070 uc_info,
1071 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001072
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001073 /* For a2dp device reconfigure all active sessions
1074 * with new AFE encoder format based on a2dp state
1075 */
1076 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001077 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1078 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001079 audio_extn_a2dp_is_force_device_switch()) {
1080 force_routing = true;
1081 }
1082
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 /*
1084 * This function is to make sure that all the usecases that are active on
1085 * the hardware codec backend are always routed to any one device that is
1086 * handled by the hardware codec.
1087 * For example, if low-latency and deep-buffer usecases are currently active
1088 * on speaker and out_set_parameters(headset) is received on low-latency
1089 * output, then we have to make sure deep-buffer is also switched to headset,
1090 * because of the limitation that both the devices cannot be enabled
1091 * at the same time as they share the same backend.
1092 */
1093 /* Disable all the usecases on the shared backend other than the
1094 specified usecase */
1095 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1096 switch_device[i] = false;
1097
1098 list_for_each(node, &adev->usecase_list) {
1099 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001100 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1101 continue;
1102
1103 if (force_routing ||
1104 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001105 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1106 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001107 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1109 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001110 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001111 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 switch_device[usecase->id] = true;
1113 num_uc_to_switch++;
1114 }
1115 }
1116
1117 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 list_for_each(node, &adev->usecase_list) {
1119 usecase = node_to_item(node, struct audio_usecase, list);
1120 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001121 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001122 }
1123 }
1124
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001125 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001126 list_for_each(node, &adev->usecase_list) {
1127 usecase = node_to_item(node, struct audio_usecase, list);
1128 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001129 d_device = derive_playback_snd_device(usecase, uc_info,
1130 snd_device);
1131 enable_snd_device(adev, d_device);
1132 /* Update the out_snd_device before enabling the audio route */
1133 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 }
1135 }
1136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001137 /* Re-route all the usecases on the shared backend other than the
1138 specified usecase to new snd devices */
1139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001142 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001143 }
1144 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 }
1146}
1147
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001148static void check_and_route_capture_usecases(struct audio_device *adev,
1149 struct audio_usecase *uc_info,
1150 snd_device_t snd_device)
1151{
1152 struct listnode *node;
1153 struct audio_usecase *usecase;
1154 bool switch_device[AUDIO_USECASE_MAX];
1155 int i, num_uc_to_switch = 0;
1156
vivek mehta4ed66e62016-04-15 23:33:34 -07001157 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1158
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001159 /*
1160 * This function is to make sure that all the active capture usecases
1161 * are always routed to the same input sound device.
1162 * For example, if audio-record and voice-call usecases are currently
1163 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1164 * is received for voice call then we have to make sure that audio-record
1165 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1166 * because of the limitation that two devices cannot be enabled
1167 * at the same time if they share the same backend.
1168 */
1169 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1170 switch_device[i] = false;
1171
1172 list_for_each(node, &adev->usecase_list) {
1173 usecase = node_to_item(node, struct audio_usecase, list);
1174 if (usecase->type != PCM_PLAYBACK &&
1175 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001176 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001177 ((uc_info->type == VOICE_CALL &&
1178 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1179 platform_check_backends_match(snd_device,\
1180 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001181 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001182 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1183 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001184 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001185 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001186 switch_device[usecase->id] = true;
1187 num_uc_to_switch++;
1188 }
1189 }
1190
1191 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001192 list_for_each(node, &adev->usecase_list) {
1193 usecase = node_to_item(node, struct audio_usecase, list);
1194 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001195 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001196 }
1197 }
1198
1199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
1201 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001202 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001203 }
1204 }
1205
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001206 /* Re-route all the usecases on the shared backend other than the
1207 specified usecase to new snd devices */
1208 list_for_each(node, &adev->usecase_list) {
1209 usecase = node_to_item(node, struct audio_usecase, list);
1210 /* Update the in_snd_device only before enabling the audio route */
1211 if (switch_device[usecase->id] ) {
1212 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001213 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 }
1215 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216 }
1217}
1218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001219/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001220static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001222 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001223 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224
1225 switch (channels) {
1226 /*
1227 * Do not handle stereo output in Multi-channel cases
1228 * Stereo case is handled in normal playback path
1229 */
1230 case 6:
1231 ALOGV("%s: HDMI supports 5.1", __func__);
1232 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1233 break;
1234 case 8:
1235 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1236 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1237 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1238 break;
1239 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001240 ALOGE("HDMI does not support multi channel playback");
1241 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001242 break;
1243 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001244 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245}
1246
Andy Hung18859412017-08-09 11:47:21 -07001247static ssize_t read_usb_sup_sample_rates(bool is_playback,
1248 uint32_t *supported_sample_rates,
1249 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001250{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001251 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1252 supported_sample_rates,
1253 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001254#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001255 for (ssize_t i=0; i<count; i++) {
1256 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1257 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001258 }
1259#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001260 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001261}
1262
Haynes Mathew George569b7482017-05-08 14:44:27 -07001263static int read_usb_sup_channel_masks(bool is_playback,
1264 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001265 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001266{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001267 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001268 int channel_count;
1269 uint32_t num_masks = 0;
1270 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1271 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001272 }
Eric Laurent74b55762017-07-09 17:04:53 -07001273 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001274 // start from 2 channels as framework currently doesn't support mono.
1275 // TODO: consider only supporting channel index masks beyond stereo here.
1276 for (channel_count = FCC_2;
1277 channel_count <= channels && num_masks < max_masks;
1278 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001279 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1280 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001281 for (channel_count = FCC_2;
1282 channel_count <= channels && num_masks < max_masks;
1283 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001284 supported_channel_masks[num_masks++] =
1285 audio_channel_mask_for_index_assignment_from_count(channel_count);
1286 }
1287 } else {
1288 // For capture we report all supported channel masks from 1 channel up.
1289 channel_count = MIN_CHANNEL_COUNT;
1290 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1291 // indexed mask
1292 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Andy Hung88ce1d92018-10-29 18:31:12 -07001293 const audio_channel_mask_t mask =
Eric Laurent74b55762017-07-09 17:04:53 -07001294 audio_channel_in_mask_from_count(channel_count);
Andy Hung88ce1d92018-10-29 18:31:12 -07001295 supported_channel_masks[num_masks++] = mask;
1296 const audio_channel_mask_t index_mask =
1297 audio_channel_mask_for_index_assignment_from_count(channel_count);
1298 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1299 supported_channel_masks[num_masks++] = index_mask;
1300 }
Eric Laurent74b55762017-07-09 17:04:53 -07001301 }
1302 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001303#ifdef NDEBUG
1304 for (size_t i = 0; i < num_masks; ++i) {
1305 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1306 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1307 }
1308#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001309 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001310}
1311
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001312static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001313 audio_format_t *supported_formats,
1314 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001315{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001316 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001317 switch (bitwidth) {
1318 case 24:
1319 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001320 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001321 break;
1322 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001323 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001324 break;
1325 case 16:
1326 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001327 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001328 break;
1329 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001330 ALOGV("%s: %s supported format %d", __func__,
1331 is_playback ? "P" : "C", bitwidth);
1332 return 1;
1333}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001334
Haynes Mathew George569b7482017-05-08 14:44:27 -07001335static int read_usb_sup_params_and_compare(bool is_playback,
1336 audio_format_t *format,
1337 audio_format_t *supported_formats,
1338 uint32_t max_formats,
1339 audio_channel_mask_t *mask,
1340 audio_channel_mask_t *supported_channel_masks,
1341 uint32_t max_masks,
1342 uint32_t *rate,
1343 uint32_t *supported_sample_rates,
1344 uint32_t max_rates) {
1345 int ret = 0;
1346 int num_formats;
1347 int num_masks;
1348 int num_rates;
1349 int i;
1350
1351 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1352 max_formats);
1353 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1354 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001355
Haynes Mathew George569b7482017-05-08 14:44:27 -07001356 num_rates = read_usb_sup_sample_rates(is_playback,
1357 supported_sample_rates, max_rates);
1358
1359#define LUT(table, len, what, dflt) \
1360 for (i=0; i<len && (table[i] != what); i++); \
1361 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1362
1363 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1364 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1365 LUT(supported_sample_rates, num_rates, *rate, 0);
1366
1367#undef LUT
1368 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001369}
1370
Andy Hungd9653bd2017-08-01 19:31:39 -07001371static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1372{
1373 // Check if usb is ready.
1374 // The usb device may have been removed quickly after insertion and hence
1375 // no longer available. This will show up as empty channel masks, or rates.
1376
1377 pthread_mutex_lock(&adev->lock);
1378 uint32_t supported_sample_rate;
1379
1380 // we consider usb ready if we can fetch at least one sample rate.
1381 const bool ready = read_usb_sup_sample_rates(
1382 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1383 pthread_mutex_unlock(&adev->lock);
1384 return ready;
1385}
1386
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001387static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1388{
1389 struct audio_usecase *usecase;
1390 struct listnode *node;
1391
1392 list_for_each(node, &adev->usecase_list) {
1393 usecase = node_to_item(node, struct audio_usecase, list);
1394 if (usecase->type == VOICE_CALL) {
1395 ALOGV("%s: usecase id %d", __func__, usecase->id);
1396 return usecase->id;
1397 }
1398 }
1399 return USECASE_INVALID;
1400}
1401
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001402struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1403 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404{
1405 struct audio_usecase *usecase;
1406 struct listnode *node;
1407
1408 list_for_each(node, &adev->usecase_list) {
1409 usecase = node_to_item(node, struct audio_usecase, list);
1410 if (usecase->id == uc_id)
1411 return usecase;
1412 }
1413 return NULL;
1414}
1415
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001416static bool force_device_switch(struct audio_usecase *usecase)
1417{
1418 if (usecase->stream.out == NULL) {
1419 ALOGE("%s: stream.out is NULL", __func__);
1420 return false;
1421 }
1422
1423 // Force all A2DP output devices to reconfigure for proper AFE encode format
1424 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1425 // in suspended state, hence try to trigger a retry when we again get a routing request.
1426 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1427 audio_extn_a2dp_is_force_device_switch()) {
1428 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1429 return true;
1430 }
1431
1432 return false;
1433}
1434
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001435struct stream_in *adev_get_active_input(const struct audio_device *adev)
1436{
1437 struct listnode *node;
1438 struct stream_in *last_active_in = NULL;
1439
1440 /* Get last added active input.
1441 * TODO: We may use a priority mechanism to pick highest priority active source */
1442 list_for_each(node, &adev->usecase_list)
1443 {
1444 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1445 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1446 last_active_in = usecase->stream.in;
1447 }
1448 }
1449
1450 return last_active_in;
1451}
1452
1453struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1454{
1455 struct listnode *node;
1456
1457 /* First check active inputs with voice communication source and then
1458 * any input if audio mode is in communication */
1459 list_for_each(node, &adev->usecase_list)
1460 {
1461 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1462 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1463 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1464 return usecase->stream.in;
1465 }
1466 }
1467 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1468 return adev_get_active_input(adev);
1469 }
1470 return NULL;
1471}
1472
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001473int select_devices(struct audio_device *adev,
1474 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001476 snd_device_t out_snd_device = SND_DEVICE_NONE;
1477 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478 struct audio_usecase *usecase = NULL;
1479 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001480 struct audio_usecase *hfp_usecase = NULL;
1481 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001482 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001483 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001484 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1485 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487 usecase = get_usecase_from_list(adev, uc_id);
1488 if (usecase == NULL) {
1489 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1490 return -EINVAL;
1491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001492
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001493 if ((usecase->type == VOICE_CALL) ||
1494 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001495 out_snd_device = platform_get_output_snd_device(adev->platform,
1496 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001497 in_snd_device = platform_get_input_snd_device(adev->platform,
1498 NULL,
1499 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 usecase->devices = usecase->stream.out->devices;
1501 } else {
1502 /*
1503 * If the voice call is active, use the sound devices of voice call usecase
1504 * so that it would not result any device switch. All the usecases will
1505 * be switched to new device when select_devices() is called for voice call
1506 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001507 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001508 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001509 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001510 vc_usecase = get_usecase_from_list(adev,
1511 get_voice_usecase_id_from_list(adev));
1512 if ((vc_usecase != NULL) &&
1513 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
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;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001560 } else if (adev->primary_output) {
1561 out_device = adev->primary_output->devices;
1562 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001563 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001564 in_snd_device = platform_get_input_snd_device(adev->platform,
1565 usecase->stream.in,
1566 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001567 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 }
1569 }
1570
1571 if (out_snd_device == usecase->out_snd_device &&
1572 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001573 if (!force_device_switch(usecase))
1574 return 0;
1575 }
1576
1577 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1578 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1579 return 0;
1580 }
1581
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001582 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1583 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001584 (!audio_extn_a2dp_is_ready())) {
1585 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001586 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1587 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1588 else
1589 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 }
1591
juyuchen66c4ecf2018-08-06 15:39:34 +08001592 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1593 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1594 }
1595
Eric Laurent2bafff12016-03-17 12:17:23 -07001596 if (out_snd_device != SND_DEVICE_NONE &&
1597 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1598 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1599 __func__,
1600 use_case_table[uc_id],
1601 adev->last_logged_snd_device[uc_id][0],
1602 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1603 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1604 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1605 -1,
1606 out_snd_device,
1607 platform_get_snd_device_name(out_snd_device),
1608 platform_get_snd_device_acdb_id(out_snd_device));
1609 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1610 }
1611 if (in_snd_device != SND_DEVICE_NONE &&
1612 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1613 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1614 __func__,
1615 use_case_table[uc_id],
1616 adev->last_logged_snd_device[uc_id][1],
1617 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1618 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1619 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1620 -1,
1621 in_snd_device,
1622 platform_get_snd_device_name(in_snd_device),
1623 platform_get_snd_device_acdb_id(in_snd_device));
1624 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1625 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 /*
1628 * Limitation: While in call, to do a device switch we need to disable
1629 * and enable both RX and TX devices though one of them is same as current
1630 * device.
1631 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001632 if ((usecase->type == VOICE_CALL) &&
1633 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1634 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001635 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001636 /* Disable sidetone only if voice call already exists */
1637 if (voice_is_call_state_active(adev))
1638 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001639 }
1640
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 /* Disable current sound devices */
1642 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001643 disable_audio_route(adev, usecase);
1644 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 }
1646
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 if (usecase->in_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->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650 }
1651
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001652 /* Applicable only on the targets that has external modem.
1653 * New device information should be sent to modem before enabling
1654 * the devices to reduce in-call device switch time.
1655 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001656 if ((usecase->type == VOICE_CALL) &&
1657 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1658 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001659 status = platform_switch_voice_call_enable_device_config(adev->platform,
1660 out_snd_device,
1661 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001662 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664 /* Enable new sound devices */
1665 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001666 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001667 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1668 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001669 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001670 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 }
1672
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001673 if (in_snd_device != SND_DEVICE_NONE) {
1674 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001675 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677
Eric Laurentb23d5282013-05-14 15:27:20 -07001678 if (usecase->type == VOICE_CALL)
1679 status = platform_switch_voice_call_device_post(adev->platform,
1680 out_snd_device,
1681 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001682
sangwoo170731f2013-06-08 15:36:36 +09001683 usecase->in_snd_device = in_snd_device;
1684 usecase->out_snd_device = out_snd_device;
1685
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001686 audio_extn_tfa_98xx_set_mode();
1687
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001688 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001689
Jasmine Cha70771b62018-05-15 15:02:43 +08001690 audio_extn_ma_set_device(usecase);
jasmine cha270b7762018-03-30 15:41:33 +08001691
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001692 /* If input stream is already running the effect needs to be
1693 applied on the new input device that's being enabled here. */
1694 if (in_snd_device != SND_DEVICE_NONE)
1695 check_and_enable_effect(adev);
1696
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001697 /* Applicable only on the targets that has external modem.
1698 * Enable device command should be sent to modem only after
1699 * enabling voice call mixer controls
1700 */
vivek mehta765eb642015-08-07 19:46:06 -07001701 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001702 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1703 out_snd_device,
1704 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001705 /* Enable sidetone only if voice call already exists */
1706 if (voice_is_call_state_active(adev))
1707 voice_set_sidetone(adev, out_snd_device, true);
1708 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001709
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001710 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001711 struct stream_out *voip_out = voip_usecase->stream.out;
1712 audio_extn_utils_send_app_type_gain(adev,
1713 voip_out->app_type_cfg.app_type,
1714 &voip_out->app_type_cfg.gain[0]);
1715 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 return status;
1717}
1718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719static int stop_input_stream(struct stream_in *in)
1720{
1721 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722 struct audio_usecase *uc_info;
1723 struct audio_device *adev = in->dev;
1724
Eric Laurent994a6932013-07-17 11:51:42 -07001725 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001726 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001728 uc_info = get_usecase_from_list(adev, in->usecase);
1729 if (uc_info == NULL) {
1730 ALOGE("%s: Could not find the usecase (%d) in the list",
1731 __func__, in->usecase);
1732 return -EINVAL;
1733 }
1734
vivek mehta781065c2017-04-04 12:55:01 -07001735 /* Close in-call recording streams */
1736 voice_check_and_stop_incall_rec_usecase(adev, in);
1737
Eric Laurent150dbfe2013-02-27 14:31:02 -08001738 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001739 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740
1741 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001742 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001744 list_remove(&uc_info->list);
1745 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001746
Eric Laurent994a6932013-07-17 11:51:42 -07001747 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 return ret;
1749}
1750
1751int start_input_stream(struct stream_in *in)
1752{
1753 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001754 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 struct audio_usecase *uc_info;
1756 struct audio_device *adev = in->dev;
1757
Eric Laurent994a6932013-07-17 11:51:42 -07001758 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001759
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001760 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1761 return -EIO;
1762
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001763 if (in->card_status == CARD_STATUS_OFFLINE ||
1764 adev->card_status == CARD_STATUS_OFFLINE) {
1765 ALOGW("in->card_status or adev->card_status offline, try again");
1766 ret = -EAGAIN;
1767 goto error_config;
1768 }
1769
vivek mehta781065c2017-04-04 12:55:01 -07001770 /* Check if source matches incall recording usecase criteria */
1771 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1772 if (ret)
1773 goto error_config;
1774 else
1775 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1776
Eric Laurentb23d5282013-05-14 15:27:20 -07001777 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 if (in->pcm_device_id < 0) {
1779 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1780 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001781 ret = -EINVAL;
1782 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1786 uc_info->id = in->usecase;
1787 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001788 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 uc_info->devices = in->device;
1790 uc_info->in_snd_device = SND_DEVICE_NONE;
1791 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001793 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001794
Wei Wangf4837d52017-11-21 14:51:20 -08001795 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001796 audio_extn_perf_lock_acquire();
1797
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001798 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799
Eric Laurent0e46adf2016-12-16 12:49:24 -08001800 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001801 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001802 ALOGE("%s: pcm stream not ready", __func__);
1803 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001804 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001805 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001806 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001807 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1808 goto error_open;
1809 }
1810 } else {
1811 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1812 unsigned int pcm_open_retry_count = 0;
1813
1814 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1815 flags |= PCM_MMAP | PCM_NOIRQ;
1816 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1817 } else if (in->realtime) {
1818 flags |= PCM_MMAP | PCM_NOIRQ;
1819 }
1820
1821 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1822 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1823
1824 while (1) {
1825 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1826 flags, &in->config);
1827 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1828 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1829 if (in->pcm != NULL) {
1830 pcm_close(in->pcm);
1831 in->pcm = NULL;
1832 }
1833 if (pcm_open_retry_count-- == 0) {
1834 ret = -EIO;
1835 goto error_open;
1836 }
1837 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1838 continue;
1839 }
1840 break;
1841 }
1842
1843 ALOGV("%s: pcm_prepare", __func__);
1844 ret = pcm_prepare(in->pcm);
1845 if (ret < 0) {
1846 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001847 pcm_close(in->pcm);
1848 in->pcm = NULL;
1849 goto error_open;
1850 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001851 if (in->realtime) {
1852 ret = pcm_start(in->pcm);
1853 if (ret < 0) {
1854 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1855 pcm_close(in->pcm);
1856 in->pcm = NULL;
1857 goto error_open;
1858 }
1859 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001860 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001861 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001862 check_and_enable_effect(adev);
Wei Wangf4837d52017-11-21 14:51:20 -08001863 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001864 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001865 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001866
Eric Laurent0e46adf2016-12-16 12:49:24 -08001867 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001868
1869error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001871 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001872 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001873
1874error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001875 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001876 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001877}
1878
Eric Laurenta1478072015-09-21 17:21:52 -07001879void lock_input_stream(struct stream_in *in)
1880{
1881 pthread_mutex_lock(&in->pre_lock);
1882 pthread_mutex_lock(&in->lock);
1883 pthread_mutex_unlock(&in->pre_lock);
1884}
1885
1886void lock_output_stream(struct stream_out *out)
1887{
1888 pthread_mutex_lock(&out->pre_lock);
1889 pthread_mutex_lock(&out->lock);
1890 pthread_mutex_unlock(&out->pre_lock);
1891}
1892
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001893/* must be called with out->lock locked */
1894static int send_offload_cmd_l(struct stream_out* out, int command)
1895{
1896 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1897
1898 ALOGVV("%s %d", __func__, command);
1899
1900 cmd->cmd = command;
1901 list_add_tail(&out->offload_cmd_list, &cmd->node);
1902 pthread_cond_signal(&out->offload_cond);
1903 return 0;
1904}
1905
1906/* must be called iwth out->lock locked */
1907static void stop_compressed_output_l(struct stream_out *out)
1908{
1909 out->offload_state = OFFLOAD_STATE_IDLE;
1910 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001911 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001912 if (out->compr != NULL) {
1913 compress_stop(out->compr);
1914 while (out->offload_thread_blocked) {
1915 pthread_cond_wait(&out->cond, &out->lock);
1916 }
1917 }
1918}
1919
1920static void *offload_thread_loop(void *context)
1921{
1922 struct stream_out *out = (struct stream_out *) context;
1923 struct listnode *item;
1924
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001925 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1926 set_sched_policy(0, SP_FOREGROUND);
1927 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1928
1929 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001930
Eric Laurenta1478072015-09-21 17:21:52 -07001931 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001932 out->offload_state = OFFLOAD_STATE_IDLE;
1933 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001934 for (;;) {
1935 struct offload_cmd *cmd = NULL;
1936 stream_callback_event_t event;
1937 bool send_callback = false;
1938
1939 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1940 __func__, list_empty(&out->offload_cmd_list),
1941 out->offload_state);
1942 if (list_empty(&out->offload_cmd_list)) {
1943 ALOGV("%s SLEEPING", __func__);
1944 pthread_cond_wait(&out->offload_cond, &out->lock);
1945 ALOGV("%s RUNNING", __func__);
1946 continue;
1947 }
1948
1949 item = list_head(&out->offload_cmd_list);
1950 cmd = node_to_item(item, struct offload_cmd, node);
1951 list_remove(item);
1952
1953 ALOGVV("%s STATE %d CMD %d out->compr %p",
1954 __func__, out->offload_state, cmd->cmd, out->compr);
1955
1956 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1957 free(cmd);
1958 break;
1959 }
1960
1961 if (out->compr == NULL) {
1962 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001963 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 pthread_cond_signal(&out->cond);
1965 continue;
1966 }
1967 out->offload_thread_blocked = true;
1968 pthread_mutex_unlock(&out->lock);
1969 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001970 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001971 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1972 compress_wait(out->compr, -1);
1973 send_callback = true;
1974 event = STREAM_CBK_EVENT_WRITE_READY;
1975 break;
1976 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001977 compress_next_track(out->compr);
1978 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001979 send_callback = true;
1980 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001981 /* Resend the metadata for next iteration */
1982 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983 break;
1984 case OFFLOAD_CMD_DRAIN:
1985 compress_drain(out->compr);
1986 send_callback = true;
1987 event = STREAM_CBK_EVENT_DRAIN_READY;
1988 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001989 case OFFLOAD_CMD_ERROR:
1990 send_callback = true;
1991 event = STREAM_CBK_EVENT_ERROR;
1992 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001993 default:
1994 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1995 break;
1996 }
Eric Laurenta1478072015-09-21 17:21:52 -07001997 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001998 out->offload_thread_blocked = false;
1999 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002000 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002001 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002002 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002003 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 free(cmd);
2005 }
2006
2007 pthread_cond_signal(&out->cond);
2008 while (!list_empty(&out->offload_cmd_list)) {
2009 item = list_head(&out->offload_cmd_list);
2010 list_remove(item);
2011 free(node_to_item(item, struct offload_cmd, node));
2012 }
2013 pthread_mutex_unlock(&out->lock);
2014
2015 return NULL;
2016}
2017
2018static int create_offload_callback_thread(struct stream_out *out)
2019{
2020 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2021 list_init(&out->offload_cmd_list);
2022 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2023 offload_thread_loop, out);
2024 return 0;
2025}
2026
2027static int destroy_offload_callback_thread(struct stream_out *out)
2028{
Eric Laurenta1478072015-09-21 17:21:52 -07002029 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 stop_compressed_output_l(out);
2031 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2032
2033 pthread_mutex_unlock(&out->lock);
2034 pthread_join(out->offload_thread, (void **) NULL);
2035 pthread_cond_destroy(&out->offload_cond);
2036
2037 return 0;
2038}
2039
Eric Laurent07eeafd2013-10-06 12:52:49 -07002040static bool allow_hdmi_channel_config(struct audio_device *adev)
2041{
2042 struct listnode *node;
2043 struct audio_usecase *usecase;
2044 bool ret = true;
2045
2046 list_for_each(node, &adev->usecase_list) {
2047 usecase = node_to_item(node, struct audio_usecase, list);
2048 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2049 /*
2050 * If voice call is already existing, do not proceed further to avoid
2051 * disabling/enabling both RX and TX devices, CSD calls, etc.
2052 * Once the voice call done, the HDMI channels can be configured to
2053 * max channels of remaining use cases.
2054 */
2055 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002056 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002057 __func__);
2058 ret = false;
2059 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002060 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2061 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002062 "no change in HDMI channels", __func__);
2063 ret = false;
2064 break;
2065 }
2066 }
2067 }
2068 return ret;
2069}
2070
2071static int check_and_set_hdmi_channels(struct audio_device *adev,
2072 unsigned int channels)
2073{
2074 struct listnode *node;
2075 struct audio_usecase *usecase;
2076
2077 /* Check if change in HDMI channel config is allowed */
2078 if (!allow_hdmi_channel_config(adev))
2079 return 0;
2080
2081 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002082 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002083 return 0;
2084 }
2085
2086 platform_set_hdmi_channels(adev->platform, channels);
2087 adev->cur_hdmi_channels = channels;
2088
2089 /*
2090 * Deroute all the playback streams routed to HDMI so that
2091 * the back end is deactivated. Note that backend will not
2092 * be deactivated if any one stream is connected to it.
2093 */
2094 list_for_each(node, &adev->usecase_list) {
2095 usecase = node_to_item(node, struct audio_usecase, list);
2096 if (usecase->type == PCM_PLAYBACK &&
2097 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002098 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002099 }
2100 }
2101
2102 /*
2103 * Enable all the streams disabled above. Now the HDMI backend
2104 * will be activated with new channel configuration
2105 */
2106 list_for_each(node, &adev->usecase_list) {
2107 usecase = node_to_item(node, struct audio_usecase, list);
2108 if (usecase->type == PCM_PLAYBACK &&
2109 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002110 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002111 }
2112 }
2113
2114 return 0;
2115}
2116
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002117static int check_and_set_usb_service_interval(struct audio_device *adev,
2118 struct audio_usecase *uc_info,
2119 bool min)
2120{
2121 struct listnode *node;
2122 struct audio_usecase *usecase;
2123 bool switch_usecases = false;
2124 bool reconfig = false;
2125
2126 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2127 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2128 return -1;
2129
2130 /* set if the valid usecase do not already exist */
2131 list_for_each(node, &adev->usecase_list) {
2132 usecase = node_to_item(node, struct audio_usecase, list);
2133 if (usecase->type == PCM_PLAYBACK &&
2134 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2135 switch (usecase->id) {
2136 case USECASE_AUDIO_PLAYBACK_MMAP:
2137 case USECASE_AUDIO_PLAYBACK_ULL:
2138 // cannot reconfig while mmap/ull is present.
2139 return -1;
2140 default:
2141 switch_usecases = true;
2142 break;
2143 }
2144 }
2145 if (switch_usecases)
2146 break;
2147 }
2148 /*
2149 * client can try to set service interval in start_output_stream
2150 * to min or to 0 (i.e reset) in stop_output_stream .
2151 */
2152 unsigned long service_interval =
2153 audio_extn_usb_find_service_interval(min, true /*playback*/);
2154 int ret = platform_set_usb_service_interval(adev->platform,
2155 true /*playback*/,
2156 service_interval,
2157 &reconfig);
2158 /* no change or not supported or no active usecases */
2159 if (ret || !reconfig || !switch_usecases)
2160 return -1;
2161 return 0;
2162#undef VALID_USECASE
2163}
2164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165static int stop_output_stream(struct stream_out *out)
2166{
2167 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 struct audio_usecase *uc_info;
2169 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002170 bool has_voip_usecase =
2171 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Eric Laurent994a6932013-07-17 11:51:42 -07002173 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002174 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 uc_info = get_usecase_from_list(adev, out->usecase);
2176 if (uc_info == NULL) {
2177 ALOGE("%s: Could not find the usecase (%d) in the list",
2178 __func__, out->usecase);
2179 return -EINVAL;
2180 }
2181
Haynes Mathew George41f86652014-06-17 14:22:15 -07002182 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2183 if (adev->visualizer_stop_output != NULL)
2184 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2185 if (adev->offload_effects_stop_output != NULL)
2186 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002187 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2188 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2189 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002190 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002191
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002192 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2193 voice_set_device_mute_flag(adev, false);
2194
Eric Laurent150dbfe2013-02-27 14:31:02 -08002195 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002196 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197
2198 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002199 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002201 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202
Eric Laurent0499d4f2014-08-25 22:39:29 -05002203 audio_extn_extspk_update(adev->extspk);
2204
Eric Laurent07eeafd2013-10-06 12:52:49 -07002205 /* Must be called after removing the usecase from list */
2206 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2207 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002208 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002209 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2210 if (ret == 0) {
2211 /* default service interval was successfully updated,
2212 reopen USB backend with new service interval */
2213 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2214 }
2215 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002216 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002217
HW Lee88512e92018-06-12 15:26:09 +08002218 if (has_voip_usecase ||
2219 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2220 struct listnode *node;
2221 struct audio_usecase *usecase;
2222 list_for_each(node, &adev->usecase_list) {
2223 usecase = node_to_item(node, struct audio_usecase, list);
2224 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
2225 continue;
2226
2227 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2228 __func__, usecase->id, use_case_table[usecase->id],
2229 out->usecase, use_case_table[out->usecase]);
2230 select_devices(adev, usecase->id);
2231 }
2232 }
2233
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002234 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002235 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002236 return ret;
2237}
2238
2239int start_output_stream(struct stream_out *out)
2240{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242 struct audio_usecase *uc_info;
2243 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002244 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Eric Laurent994a6932013-07-17 11:51:42 -07002246 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002248
2249 if (out->card_status == CARD_STATUS_OFFLINE ||
2250 adev->card_status == CARD_STATUS_OFFLINE) {
2251 ALOGW("out->card_status or adev->card_status offline, try again");
2252 ret = -EAGAIN;
2253 goto error_config;
2254 }
2255
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002256 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2257 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002258 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002259 a2dp_combo = true;
2260 } else {
2261 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2262 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2263 ret = -EAGAIN;
2264 goto error_config;
2265 }
2266 }
2267 }
2268 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002269 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 if (out->pcm_device_id < 0) {
2271 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2272 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002273 ret = -EINVAL;
2274 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 }
2276
2277 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2278 uc_info->id = out->usecase;
2279 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002280 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 uc_info->devices = out->devices;
2282 uc_info->in_snd_device = SND_DEVICE_NONE;
2283 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284
Eric Laurent07eeafd2013-10-06 12:52:49 -07002285 /* This must be called before adding this usecase to the list */
2286 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2287 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002288 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2289 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2290 /* USB backend is not reopened immediately.
2291 This is eventually done as part of select_devices */
2292 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002293
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002294 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295
Wei Wangf4837d52017-11-21 14:51:20 -08002296 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002297 audio_extn_perf_lock_acquire();
2298
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002299 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2300 (!audio_extn_a2dp_is_ready())) {
2301 if (!a2dp_combo) {
2302 check_a2dp_restore_l(adev, out, false);
2303 } else {
2304 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002305 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2306 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2307 else
2308 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002309 select_devices(adev, out->usecase);
2310 out->devices = dev;
2311 }
2312 } else {
2313 select_devices(adev, out->usecase);
2314 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002315
Eric Laurent0499d4f2014-08-25 22:39:29 -05002316 audio_extn_extspk_update(adev->extspk);
2317
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002318 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2319 voice_set_device_mute_flag(adev, true);
2320
Andy Hung31aca912014-03-20 17:14:59 -07002321 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002322 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002323 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2324 out->pcm = NULL;
2325 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2326 COMPRESS_IN, &out->compr_config);
2327 if (out->compr && !is_compress_ready(out->compr)) {
2328 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2329 compress_close(out->compr);
2330 out->compr = NULL;
2331 ret = -EIO;
2332 goto error_open;
2333 }
2334 if (out->offload_callback)
2335 compress_nonblock(out->compr, out->non_blocking);
2336
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002337 if (adev->visualizer_start_output != NULL) {
2338 int capture_device_id =
2339 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2340 PCM_CAPTURE);
2341 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2342 adev->snd_card, capture_device_id);
2343 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002344 if (adev->offload_effects_start_output != NULL)
2345 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2346 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002347 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002348 ALOGE("%s: pcm stream not ready", __func__);
2349 goto error_open;
2350 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002351 ret = pcm_start(out->pcm);
2352 if (ret < 0) {
2353 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2354 goto error_open;
2355 }
2356 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002357 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002358 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002359
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002360 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2361 flags |= PCM_MMAP | PCM_NOIRQ;
2362 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002363 } else if (out->realtime) {
2364 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002365 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002366
2367 while (1) {
2368 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2369 flags, &out->config);
2370 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2371 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2372 if (out->pcm != NULL) {
2373 pcm_close(out->pcm);
2374 out->pcm = NULL;
2375 }
2376 if (pcm_open_retry_count-- == 0) {
2377 ret = -EIO;
2378 goto error_open;
2379 }
2380 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2381 continue;
2382 }
2383 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002385 ALOGV("%s: pcm_prepare", __func__);
2386 if (pcm_is_ready(out->pcm)) {
2387 ret = pcm_prepare(out->pcm);
2388 if (ret < 0) {
2389 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2390 pcm_close(out->pcm);
2391 out->pcm = NULL;
2392 goto error_open;
2393 }
2394 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002395 if (out->realtime) {
2396 ret = pcm_start(out->pcm);
2397 if (ret < 0) {
2398 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2399 pcm_close(out->pcm);
2400 out->pcm = NULL;
2401 goto error_open;
2402 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002403 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002404 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002405 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002406 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002407 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002408 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002409
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002410 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2411 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2412 audio_low_latency_hint_start();
2413 }
2414
vivek mehtae59cfb22017-06-16 15:57:11 -07002415 // consider a scenario where on pause lower layers are tear down.
2416 // so on resume, swap mixer control need to be sent only when
2417 // backend is active, hence rather than sending from enable device
2418 // sending it from start of streamtream
2419
2420 platform_set_swap_channels(adev, true);
2421
Eric Laurent994a6932013-07-17 11:51:42 -07002422 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002423 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002425 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002426 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002428error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002429 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430}
2431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432static int check_input_parameters(uint32_t sample_rate,
2433 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002434 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002436 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2437 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002438 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2439 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002440 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2441 return -EINVAL;
2442 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443
Eric Laurent74b55762017-07-09 17:04:53 -07002444 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2445 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002446 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002447 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002448 return -EINVAL;
2449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450
2451 switch (sample_rate) {
2452 case 8000:
2453 case 11025:
2454 case 12000:
2455 case 16000:
2456 case 22050:
2457 case 24000:
2458 case 32000:
2459 case 44100:
2460 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002461 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 break;
2463 default:
vivek mehtadae44712015-07-27 14:13:18 -07002464 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 return -EINVAL;
2466 }
2467
2468 return 0;
2469}
2470
Kevin Rocarda325aa22018-04-03 09:15:52 -07002471/** Add a value in a list if not already present.
2472 * @return true if value was successfully inserted or already present,
2473 * false if the list is full and does not contain the value.
2474 */
2475static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2476 for (size_t i = 0; i < list_length; i++) {
2477 if (list[i] == value) return true; // value is already present
2478 if (list[i] == 0) { // no values in this slot
2479 list[i] = value;
2480 return true; // value inserted
2481 }
2482 }
2483 return false; // could not insert value
2484}
2485
2486/** Add channel_mask in supported_channel_masks if not already present.
2487 * @return true if channel_mask was successfully inserted or already present,
2488 * false if supported_channel_masks is full and does not contain channel_mask.
2489 */
2490static void register_channel_mask(audio_channel_mask_t channel_mask,
2491 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2492 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2493 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2494}
2495
2496/** Add format in supported_formats if not already present.
2497 * @return true if format was successfully inserted or already present,
2498 * false if supported_formats is full and does not contain format.
2499 */
2500static void register_format(audio_format_t format,
2501 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2502 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2503 "%s: stream can not declare supporting its format %x", __func__, format);
2504}
2505/** Add sample_rate in supported_sample_rates if not already present.
2506 * @return true if sample_rate was successfully inserted or already present,
2507 * false if supported_sample_rates is full and does not contain sample_rate.
2508 */
2509static void register_sample_rate(uint32_t sample_rate,
2510 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2511 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2512 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2513}
2514
vivek mehtaa68fea62017-06-08 19:04:02 -07002515static size_t get_stream_buffer_size(size_t duration_ms,
2516 uint32_t sample_rate,
2517 audio_format_t format,
2518 int channel_count,
2519 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520{
2521 size_t size = 0;
2522
vivek mehtaa68fea62017-06-08 19:04:02 -07002523 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002524 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002525 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002526
2527 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
Glenn Kasten4f993392014-05-14 07:30:48 -07002529 /* make sure the size is multiple of 32 bytes
2530 * At 48 kHz mono 16-bit PCM:
2531 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2532 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2533 */
2534 size += 0x1f;
2535 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002536
2537 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538}
2539
2540static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2541{
2542 struct stream_out *out = (struct stream_out *)stream;
2543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545}
2546
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002547static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548{
2549 return -ENOSYS;
2550}
2551
2552static size_t out_get_buffer_size(const struct audio_stream *stream)
2553{
2554 struct stream_out *out = (struct stream_out *)stream;
2555
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2557 return out->compr_config.fragment_size;
2558 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002559 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002560 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561}
2562
2563static uint32_t out_get_channels(const struct audio_stream *stream)
2564{
2565 struct stream_out *out = (struct stream_out *)stream;
2566
2567 return out->channel_mask;
2568}
2569
2570static audio_format_t out_get_format(const struct audio_stream *stream)
2571{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 struct stream_out *out = (struct stream_out *)stream;
2573
2574 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575}
2576
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002577static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578{
2579 return -ENOSYS;
2580}
2581
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002582/* must be called with out->lock locked */
2583static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584{
2585 struct stream_out *out = (struct stream_out *)stream;
2586 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002587 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002590 if (adev->adm_deregister_stream)
2591 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002592 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2595 if (out->pcm) {
2596 pcm_close(out->pcm);
2597 out->pcm = NULL;
2598 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002599 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002600 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002601 out->playback_started = false;
2602 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 } else {
2604 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002605 out->gapless_mdata.encoder_delay = 0;
2606 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 if (out->compr != NULL) {
2608 compress_close(out->compr);
2609 out->compr = NULL;
2610 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002611 }
Phil Burkbc991042017-02-24 08:06:44 -08002612 if (do_stop) {
2613 stop_output_stream(out);
2614 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002615 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002617 return 0;
2618}
2619
2620static int out_standby(struct audio_stream *stream)
2621{
2622 struct stream_out *out = (struct stream_out *)stream;
2623
2624 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2625 out->usecase, use_case_table[out->usecase]);
2626
2627 lock_output_stream(out);
2628 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002630 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 return 0;
2632}
2633
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002634static int out_on_error(struct audio_stream *stream)
2635{
2636 struct stream_out *out = (struct stream_out *)stream;
2637 struct audio_device *adev = out->dev;
2638 bool do_standby = false;
2639
2640 lock_output_stream(out);
2641 if (!out->standby) {
2642 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2643 stop_compressed_output_l(out);
2644 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2645 } else
2646 do_standby = true;
2647 }
2648 pthread_mutex_unlock(&out->lock);
2649
2650 if (do_standby)
2651 return out_standby(&out->stream.common);
2652
2653 return 0;
2654}
2655
Andy Hung7401c7c2016-09-21 12:41:21 -07002656static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657{
Andy Hung7401c7c2016-09-21 12:41:21 -07002658 struct stream_out *out = (struct stream_out *)stream;
2659
2660 // We try to get the lock for consistency,
2661 // but it isn't necessary for these variables.
2662 // If we're not in standby, we may be blocked on a write.
2663 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2664 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2665 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2666
Andy Hung572633e2019-02-19 11:58:24 -08002667 char buffer[256]; // for statistics formatting
2668 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2669 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2670
Andy Hung7401c7c2016-09-21 12:41:21 -07002671 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002672 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002673 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002674
2675 // dump error info
2676 (void)error_log_dump(
2677 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679 return 0;
2680}
2681
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002682static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2683{
2684 int ret = 0;
2685 char value[32];
2686 struct compr_gapless_mdata tmp_mdata;
2687
2688 if (!out || !parms) {
2689 return -EINVAL;
2690 }
2691
2692 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2693 if (ret >= 0) {
2694 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2695 } else {
2696 return -EINVAL;
2697 }
2698
2699 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2700 if (ret >= 0) {
2701 tmp_mdata.encoder_padding = atoi(value);
2702 } else {
2703 return -EINVAL;
2704 }
2705
2706 out->gapless_mdata = tmp_mdata;
2707 out->send_new_metadata = 1;
2708 ALOGV("%s new encoder delay %u and padding %u", __func__,
2709 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2710
2711 return 0;
2712}
2713
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002714static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2715{
2716 return out == adev->primary_output || out == adev->voice_tx_output;
2717}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002718
Kevin Rocard1e02c882017-08-09 15:26:07 -07002719static int get_alive_usb_card(struct str_parms* parms) {
2720 int card;
2721 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2722 !audio_extn_usb_alive(card)) {
2723 return card;
2724 }
2725 return -ENODEV;
2726}
2727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2729{
2730 struct stream_out *out = (struct stream_out *)stream;
2731 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002732 struct audio_usecase *usecase;
2733 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 struct str_parms *parms;
2735 char value[32];
2736 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002737 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002738 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002739 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740
Eric Laurent2e140aa2016-06-30 17:14:46 -07002741 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002742 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743 parms = str_parms_create_str(kvpairs);
2744 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2745 if (ret >= 0) {
2746 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002747
Eric Laurenta1478072015-09-21 17:21:52 -07002748 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002749
2750 // The usb driver needs to be closed after usb device disconnection
2751 // otherwise audio is no longer played on the new usb devices.
2752 // By forcing the stream in standby, the usb stack refcount drops to 0
2753 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002754 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002755 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002756 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2757 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2758 out_standby_l(&out->stream.common);
2759 }
2760 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002761 }
2762
Eric Laurent150dbfe2013-02-27 14:31:02 -08002763 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002765 /*
2766 * When HDMI cable is unplugged the music playback is paused and
2767 * the policy manager sends routing=0. But the audioflinger
2768 * continues to write data until standby time (3sec).
2769 * As the HDMI core is turned off, the write gets blocked.
2770 * Avoid this by routing audio to speaker until standby.
2771 */
2772 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2773 val == AUDIO_DEVICE_NONE) {
2774 val = AUDIO_DEVICE_OUT_SPEAKER;
2775 }
2776
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002777 /*
2778 * When A2DP is disconnected the
2779 * music playback is paused and the policy manager sends routing=0
2780 * But the audioflingercontinues to write data until standby time
2781 * (3sec). As BT is turned off, the write gets blocked.
2782 * Avoid this by routing audio to speaker until standby.
2783 */
2784 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2785 (val == AUDIO_DEVICE_NONE) &&
2786 !audio_extn_a2dp_is_ready()) {
2787 val = AUDIO_DEVICE_OUT_SPEAKER;
2788 }
2789
2790 /* To avoid a2dp to sco overlapping / BT device improper state
2791 * check with BT lib about a2dp streaming support before routing
2792 */
2793 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2794 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002795 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002796 //combo usecase just by pass a2dp
2797 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2798 bypass_a2dp = true;
2799 } else {
2800 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2801 /* update device to a2dp and don't route as BT returned error
2802 * However it is still possible a2dp routing called because
2803 * of current active device disconnection (like wired headset)
2804 */
2805 out->devices = val;
2806 pthread_mutex_unlock(&out->lock);
2807 pthread_mutex_unlock(&adev->lock);
2808 status = -ENOSYS;
2809 goto routing_fail;
2810 }
2811 }
2812 }
2813
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002814 audio_devices_t new_dev = val;
2815
2816 // Workaround: If routing to an non existing usb device, fail gracefully
2817 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002818 int card;
2819 if (audio_is_usb_out_device(new_dev) &&
2820 (card = get_alive_usb_card(parms)) >= 0) {
2821
2822 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002823 pthread_mutex_unlock(&adev->lock);
2824 pthread_mutex_unlock(&out->lock);
2825 status = -ENOSYS;
2826 goto routing_fail;
2827 }
2828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 /*
2830 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002831 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002832 * the select_devices(). But how do we undo this?
2833 *
2834 * For example, music playback is active on headset (deep-buffer usecase)
2835 * and if we go to ringtones and select a ringtone, low-latency usecase
2836 * will be started on headset+speaker. As we can't enable headset+speaker
2837 * and headset devices at the same time, select_devices() switches the music
2838 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2839 * So when the ringtone playback is completed, how do we undo the same?
2840 *
2841 * We are relying on the out_set_parameters() call on deep-buffer output,
2842 * once the ringtone playback is ended.
2843 * NOTE: We should not check if the current devices are same as new devices.
2844 * Because select_devices() must be called to switch back the music
2845 * playback to headset.
2846 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002847 if (new_dev != AUDIO_DEVICE_NONE) {
2848 bool same_dev = out->devices == new_dev;
2849 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002850
Eric Laurenta7657192014-10-09 21:09:33 -07002851 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002852 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002853 if (adev->mode == AUDIO_MODE_IN_CALL) {
2854 adev->current_call_output = out;
2855 ret = voice_start_call(adev);
2856 }
2857 } else {
2858 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002859 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002860 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002861 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002862
2863 if (!out->standby) {
2864 if (!same_dev) {
2865 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002866 // inform adm before actual routing to prevent glitches.
2867 if (adev->adm_on_routing_change) {
2868 adev->adm_on_routing_change(adev->adm_data,
2869 out->handle);
2870 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002871 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002872 if (!bypass_a2dp) {
2873 select_devices(adev, out->usecase);
2874 } else {
juyuchen9baad392018-06-05 19:02:10 +08002875 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2876 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2877 else
2878 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002879 select_devices(adev, out->usecase);
2880 out->devices = new_dev;
2881 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002882 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002883
2884 // on device switch force swap, lower functions will make sure
2885 // to check if swap is allowed or not.
2886
2887 if (!same_dev)
2888 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002889
2890 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2891 out->a2dp_compress_mute &&
2892 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2893 pthread_mutex_lock(&out->compr_mute_lock);
2894 out->a2dp_compress_mute = false;
2895 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2896 pthread_mutex_unlock(&out->compr_mute_lock);
2897 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002898 }
2899
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002900 }
2901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002903 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002904
2905 /*handles device and call state changes*/
2906 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002907 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002908 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002909
2910 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2911 parse_compress_metadata(out, parms);
2912 }
2913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002914 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002915 ALOGV("%s: exit: code(%d)", __func__, status);
2916 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917}
2918
Haynes Mathew George569b7482017-05-08 14:44:27 -07002919static bool stream_get_parameter_channels(struct str_parms *query,
2920 struct str_parms *reply,
2921 audio_channel_mask_t *supported_channel_masks) {
2922 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07002923 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002925 size_t i, j;
2926
2927 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2928 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 value[0] = '\0';
2930 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002931 while (supported_channel_masks[i] != 0) {
2932 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2933 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 if (!first) {
2935 strcat(value, "|");
2936 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002937 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 first = false;
2939 break;
2940 }
2941 }
2942 i++;
2943 }
2944 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002945 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002946 return ret >= 0;
2947}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002948
Haynes Mathew George569b7482017-05-08 14:44:27 -07002949static bool stream_get_parameter_formats(struct str_parms *query,
2950 struct str_parms *reply,
2951 audio_format_t *supported_formats) {
2952 int ret = -1;
2953 char value[256];
2954 int i;
2955
2956 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2957 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002958 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002959 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002960 case AUDIO_FORMAT_PCM_16_BIT:
2961 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2962 break;
2963 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2964 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2965 break;
2966 case AUDIO_FORMAT_PCM_32_BIT:
2967 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2968 break;
2969 default:
2970 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002971 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002972 break;
2973 }
2974 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002975 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002976 return ret >= 0;
2977}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002978
Haynes Mathew George569b7482017-05-08 14:44:27 -07002979static bool stream_get_parameter_rates(struct str_parms *query,
2980 struct str_parms *reply,
2981 uint32_t *supported_sample_rates) {
2982
2983 int i;
2984 char value[256];
2985 int ret = -1;
2986 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2987 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002988 value[0] = '\0';
2989 i=0;
2990 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002991 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002992 int avail = sizeof(value) - cursor;
2993 ret = snprintf(value + cursor, avail, "%s%d",
2994 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002995 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002996 if (ret < 0 || ret >= avail) {
2997 // if cursor is at the last element of the array
2998 // overwrite with \0 is duplicate work as
2999 // snprintf already put a \0 in place.
3000 // else
3001 // we had space to write the '|' at value[cursor]
3002 // (which will be overwritten) or no space to fill
3003 // the first element (=> cursor == 0)
3004 value[cursor] = '\0';
3005 break;
3006 }
3007 cursor += ret;
3008 ++i;
3009 }
3010 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3011 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003012 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003013 return ret >= 0;
3014}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003015
Haynes Mathew George569b7482017-05-08 14:44:27 -07003016static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3017{
3018 struct stream_out *out = (struct stream_out *)stream;
3019 struct str_parms *query = str_parms_create_str(keys);
3020 char *str;
3021 struct str_parms *reply = str_parms_create();
3022 bool replied = false;
3023 ALOGV("%s: enter: keys - %s", __func__, keys);
3024
3025 replied |= stream_get_parameter_channels(query, reply,
3026 &out->supported_channel_masks[0]);
3027 replied |= stream_get_parameter_formats(query, reply,
3028 &out->supported_formats[0]);
3029 replied |= stream_get_parameter_rates(query, reply,
3030 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003031 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 str = str_parms_to_str(reply);
3033 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003034 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 }
3036 str_parms_destroy(query);
3037 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003038 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 return str;
3040}
3041
3042static uint32_t out_get_latency(const struct audio_stream_out *stream)
3043{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003044 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003046 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3049 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003050 else if ((out->realtime) ||
3051 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003052 // since the buffer won't be filled up faster than realtime,
3053 // return a smaller number
3054 period_ms = (out->af_period_multiplier * out->config.period_size *
3055 1000) / (out->config.rate);
3056 hw_delay = platform_render_latency(out->usecase)/1000;
3057 return period_ms + hw_delay;
3058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003060 latency = (out->config.period_count * out->config.period_size * 1000) /
3061 (out->config.rate);
3062
3063 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3064 latency += audio_extn_a2dp_get_encoder_latency();
3065
3066 return latency;
3067}
3068
3069static int set_compr_volume(struct audio_stream_out *stream, float left,
3070 float right)
3071{
3072 struct stream_out *out = (struct stream_out *)stream;
3073 int volume[2];
3074 char mixer_ctl_name[128];
3075 struct audio_device *adev = out->dev;
3076 struct mixer_ctl *ctl;
3077 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3078 PCM_PLAYBACK);
3079
3080 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3081 "Compress Playback %d Volume", pcm_device_id);
3082 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3083 if (!ctl) {
3084 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3085 __func__, mixer_ctl_name);
3086 return -EINVAL;
3087 }
3088 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3089 __func__, mixer_ctl_name, left, right);
3090 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3091 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3092 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3093
3094 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095}
3096
3097static int out_set_volume(struct audio_stream_out *stream, float left,
3098 float right)
3099{
Eric Laurenta9024de2013-04-04 09:19:12 -07003100 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003101 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003103 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003104 /* only take left channel into account: the API is for stereo anyway */
3105 out->muted = (left == 0.0f);
3106 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003108 pthread_mutex_lock(&out->compr_mute_lock);
3109 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3110 if (!out->a2dp_compress_mute)
3111 ret = set_compr_volume(stream, left, right);
3112 out->volume_l = left;
3113 out->volume_r = right;
3114 pthread_mutex_unlock(&out->compr_mute_lock);
3115 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003116 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003117 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3118 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3119 if (!out->standby) {
3120 // if in standby, cached volume will be sent after stream is opened
3121 audio_extn_utils_send_app_type_gain(out->dev,
3122 out->app_type_cfg.app_type,
3123 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003124 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003125 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003126 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128 return -ENOSYS;
3129}
3130
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003131// note: this call is safe only if the stream_cb is
3132// removed first in close_output_stream (as is done now).
3133static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3134{
3135 if (!stream || !parms)
3136 return;
3137
3138 struct stream_out *out = (struct stream_out *)stream;
3139 struct audio_device *adev = out->dev;
3140
3141 card_status_t status;
3142 int card;
3143 if (parse_snd_card_status(parms, &card, &status) < 0)
3144 return;
3145
3146 pthread_mutex_lock(&adev->lock);
3147 bool valid_cb = (card == adev->snd_card);
3148 pthread_mutex_unlock(&adev->lock);
3149
3150 if (!valid_cb)
3151 return;
3152
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003153 lock_output_stream(out);
3154 if (out->card_status != status)
3155 out->card_status = status;
3156 pthread_mutex_unlock(&out->lock);
3157
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003158 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3159 use_case_table[out->usecase],
3160 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3161
3162 if (status == CARD_STATUS_OFFLINE)
3163 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003164
3165 return;
3166}
3167
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003168#ifdef NO_AUDIO_OUT
3169static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003170 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003171{
3172 struct stream_out *out = (struct stream_out *)stream;
3173
3174 /* No Output device supported other than BT for playback.
3175 * Sleep for the amount of buffer duration
3176 */
Eric Laurenta1478072015-09-21 17:21:52 -07003177 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003178 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3179 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003180 out_get_sample_rate(&out->stream.common));
3181 pthread_mutex_unlock(&out->lock);
3182 return bytes;
3183}
3184#endif
3185
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3187 size_t bytes)
3188{
3189 struct stream_out *out = (struct stream_out *)stream;
3190 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003191 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003192 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193
Eric Laurenta1478072015-09-21 17:21:52 -07003194 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003195 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003196 const size_t frame_size = audio_stream_out_frame_size(stream);
3197 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003198
Eric Laurent0e46adf2016-12-16 12:49:24 -08003199 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3200 error_code = ERROR_CODE_WRITE;
3201 goto exit;
3202 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003203
3204 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3205 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003206 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003207 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3208 ret = -EIO;
3209 goto exit;
3210 }
3211 }
3212 }
3213
Andy Hung572633e2019-02-19 11:58:24 -08003214 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003216 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003217 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003219
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003220 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003222 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003223 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224 goto exit;
3225 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003226
vivek mehta40125092017-08-21 18:48:51 -07003227 // after standby always force set last known cal step
3228 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3229 ALOGD("%s: retry previous failed cal level set", __func__);
3230 send_gain_dep_calibration_l();
3231 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003232
3233 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003235
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003237 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003238 if (out->send_new_metadata) {
3239 ALOGVV("send new gapless metadata");
3240 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3241 out->send_new_metadata = 0;
3242 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003243 unsigned int avail;
3244 struct timespec tstamp;
3245 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3246 /* Do not limit write size if the available frames count is unknown */
3247 if (ret != 0) {
3248 avail = bytes;
3249 }
3250 if (avail == 0) {
3251 ret = 0;
3252 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003253 // check for compressed format underrun, essentially an empty buffer check
3254 // for a lack of better measurement.
3255 if (!was_in_standby && avail == out->kernel_buffer_size) {
3256 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3257 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3258 }
3259
Eric Laurentb49b3f62016-02-29 17:59:49 -08003260 if (avail > bytes) {
3261 avail = bytes;
3262 }
3263 ret = compress_write(out->compr, buffer, avail);
3264 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3265 __func__, avail, ret);
3266 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003267
Eric Laurent6e895242013-09-05 16:10:57 -07003268 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003269 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3270 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003271 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 compress_start(out->compr);
3273 out->playback_started = 1;
3274 out->offload_state = OFFLOAD_STATE_PLAYING;
3275 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003276 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003277 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003278 } else {
3279 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003280 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003281 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003282 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003283 return ret;
3284 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003285 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003286 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003287 size_t bytes_to_write = bytes;
3288
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003289 if (out->muted)
3290 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003291 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003292 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003293 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3294 int16_t *src = (int16_t *)buffer;
3295 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003296
Eric Laurentad2dde92017-09-20 18:27:31 -07003297 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3298 out->format != AUDIO_FORMAT_PCM_16_BIT,
3299 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003300
Eric Laurentad2dde92017-09-20 18:27:31 -07003301 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3302 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3303 }
3304 bytes_to_write /= 2;
3305 }
Andy Hung572633e2019-02-19 11:58:24 -08003306
3307 // Note: since out_get_presentation_position() is called alternating with out_write()
3308 // by AudioFlinger, we can check underruns using the prior timestamp read.
3309 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3310 if (out->last_fifo_valid) {
3311 // compute drain to see if there is an underrun.
3312 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3313 const int64_t frames_by_time =
3314 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3315 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3316
3317 if (underrun > 0) {
3318 simple_stats_log(&out->fifo_underruns, underrun);
3319
3320 ALOGW("%s: underrun(%lld) "
3321 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3322 __func__,
3323 (long long)out->fifo_underruns.n,
3324 (long long)frames_by_time,
3325 (long long)out->last_fifo_frames_remaining);
3326 }
3327 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3328 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003329
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003330 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003331 request_out_focus(out, ns);
3332
3333 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3334 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07003335 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003336 else
Eric Laurentad2dde92017-09-20 18:27:31 -07003337 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003338
Haynes Mathew George03c40102016-01-29 17:57:48 -08003339 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003340 } else {
3341 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 }
3344
3345exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003346 // For PCM we always consume the buffer and return #bytes regardless of ret.
3347 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003348 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003349 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003350 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003351
Andy Hung7401c7c2016-09-21 12:41:21 -07003352 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003353 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003354 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3355 ALOGE_IF(out->pcm != NULL,
3356 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003357 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003358 // usleep not guaranteed for values over 1 second but we don't limit here.
3359 }
3360 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 pthread_mutex_unlock(&out->lock);
3363
3364 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003365 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003366 if (sleeptime_us != 0)
3367 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368 }
3369 return bytes;
3370}
3371
3372static int out_get_render_position(const struct audio_stream_out *stream,
3373 uint32_t *dsp_frames)
3374{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 struct stream_out *out = (struct stream_out *)stream;
3376 *dsp_frames = 0;
3377 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003378 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003380 unsigned long frames = 0;
3381 // TODO: check return value
3382 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3383 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 ALOGVV("%s rendered frames %d sample_rate %d",
3385 __func__, *dsp_frames, out->sample_rate);
3386 }
3387 pthread_mutex_unlock(&out->lock);
3388 return 0;
3389 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003390 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391}
3392
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003393static int out_add_audio_effect(const struct audio_stream *stream __unused,
3394 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395{
3396 return 0;
3397}
3398
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003399static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3400 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401{
3402 return 0;
3403}
3404
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003405static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3406 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003408 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409}
3410
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003411static int out_get_presentation_position(const struct audio_stream_out *stream,
3412 uint64_t *frames, struct timespec *timestamp)
3413{
3414 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003415 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003416 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003417
Eric Laurenta1478072015-09-21 17:21:52 -07003418 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003419
Eric Laurent949a0892013-09-20 09:20:13 -07003420 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3421 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003422 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003423 compress_get_tstamp(out->compr, &dsp_frames,
3424 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003425 // Adjustment accounts for A2DP encoder latency with offload usecases
3426 // Note: Encoder latency is returned in ms.
3427 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3428 unsigned long offset =
3429 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3430 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3431 }
Eric Laurent949a0892013-09-20 09:20:13 -07003432 ALOGVV("%s rendered frames %ld sample_rate %d",
3433 __func__, dsp_frames, out->sample_rate);
3434 *frames = dsp_frames;
3435 ret = 0;
3436 /* this is the best we can do */
3437 clock_gettime(CLOCK_MONOTONIC, timestamp);
3438 }
3439 } else {
3440 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003441 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003442 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003443
3444 // pcm_get_htimestamp() computes the available frames by comparing
3445 // the alsa driver hw_ptr and the appl_ptr levels.
3446 // In underrun, the hw_ptr may keep running and report an excessively
3447 // large number available number.
3448 if (avail > out->kernel_buffer_size) {
3449 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3450 __func__, avail, out->kernel_buffer_size);
3451 avail = out->kernel_buffer_size;
3452 out->last_fifo_frames_remaining = 0;
3453 } else {
3454 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3455 }
3456 out->last_fifo_valid = true;
3457 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3458
3459 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3460
3461 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3462 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3463
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003464 // This adjustment accounts for buffering after app processor.
3465 // It is based on estimated DSP latency per use case, rather than exact.
3466 signed_frames -=
3467 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3468
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003469 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3470 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3471 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3472 signed_frames -=
3473 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3474 }
3475
Eric Laurent949a0892013-09-20 09:20:13 -07003476 // It would be unusual for this value to be negative, but check just in case ...
3477 if (signed_frames >= 0) {
3478 *frames = signed_frames;
3479 ret = 0;
3480 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003481 }
3482 }
3483 }
3484
3485 pthread_mutex_unlock(&out->lock);
3486
3487 return ret;
3488}
3489
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490static int out_set_callback(struct audio_stream_out *stream,
3491 stream_callback_t callback, void *cookie)
3492{
3493 struct stream_out *out = (struct stream_out *)stream;
3494
3495 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003496 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003497 out->offload_callback = callback;
3498 out->offload_cookie = cookie;
3499 pthread_mutex_unlock(&out->lock);
3500 return 0;
3501}
3502
3503static int out_pause(struct audio_stream_out* stream)
3504{
3505 struct stream_out *out = (struct stream_out *)stream;
3506 int status = -ENOSYS;
3507 ALOGV("%s", __func__);
3508 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003509 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3511 status = compress_pause(out->compr);
3512 out->offload_state = OFFLOAD_STATE_PAUSED;
3513 }
3514 pthread_mutex_unlock(&out->lock);
3515 }
3516 return status;
3517}
3518
3519static int out_resume(struct audio_stream_out* stream)
3520{
3521 struct stream_out *out = (struct stream_out *)stream;
3522 int status = -ENOSYS;
3523 ALOGV("%s", __func__);
3524 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3525 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003526 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003527 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3528 status = compress_resume(out->compr);
3529 out->offload_state = OFFLOAD_STATE_PLAYING;
3530 }
3531 pthread_mutex_unlock(&out->lock);
3532 }
3533 return status;
3534}
3535
3536static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3537{
3538 struct stream_out *out = (struct stream_out *)stream;
3539 int status = -ENOSYS;
3540 ALOGV("%s", __func__);
3541 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003542 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3544 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3545 else
3546 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3547 pthread_mutex_unlock(&out->lock);
3548 }
3549 return status;
3550}
3551
3552static int out_flush(struct audio_stream_out* stream)
3553{
3554 struct stream_out *out = (struct stream_out *)stream;
3555 ALOGV("%s", __func__);
3556 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003557 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003558 stop_compressed_output_l(out);
3559 pthread_mutex_unlock(&out->lock);
3560 return 0;
3561 }
3562 return -ENOSYS;
3563}
3564
Eric Laurent0e46adf2016-12-16 12:49:24 -08003565static int out_stop(const struct audio_stream_out* stream)
3566{
3567 struct stream_out *out = (struct stream_out *)stream;
3568 struct audio_device *adev = out->dev;
3569 int ret = -ENOSYS;
3570
3571 ALOGV("%s", __func__);
3572 pthread_mutex_lock(&adev->lock);
3573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3574 out->playback_started && out->pcm != NULL) {
3575 pcm_stop(out->pcm);
3576 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003577 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003578 }
3579 pthread_mutex_unlock(&adev->lock);
3580 return ret;
3581}
3582
3583static int out_start(const struct audio_stream_out* stream)
3584{
3585 struct stream_out *out = (struct stream_out *)stream;
3586 struct audio_device *adev = out->dev;
3587 int ret = -ENOSYS;
3588
3589 ALOGV("%s", __func__);
3590 pthread_mutex_lock(&adev->lock);
3591 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3592 !out->playback_started && out->pcm != NULL) {
3593 ret = start_output_stream(out);
3594 if (ret == 0) {
3595 out->playback_started = true;
3596 }
3597 }
3598 pthread_mutex_unlock(&adev->lock);
3599 return ret;
3600}
3601
Phil Burkbc991042017-02-24 08:06:44 -08003602/*
3603 * Modify config->period_count based on min_size_frames
3604 */
3605static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3606{
3607 int periodCountRequested = (min_size_frames + config->period_size - 1)
3608 / config->period_size;
3609 int periodCount = MMAP_PERIOD_COUNT_MIN;
3610
3611 ALOGV("%s original config.period_size = %d config.period_count = %d",
3612 __func__, config->period_size, config->period_count);
3613
3614 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3615 periodCount *= 2;
3616 }
3617 config->period_count = periodCount;
3618
3619 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3620}
3621
Eric Laurent0e46adf2016-12-16 12:49:24 -08003622static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3623 int32_t min_size_frames,
3624 struct audio_mmap_buffer_info *info)
3625{
3626 struct stream_out *out = (struct stream_out *)stream;
3627 struct audio_device *adev = out->dev;
3628 int ret = 0;
3629 unsigned int offset1;
3630 unsigned int frames1;
3631 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003632 uint32_t mmap_size;
3633 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003634
3635 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003636 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003637 pthread_mutex_lock(&adev->lock);
3638
3639 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003640 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003641 ret = -EINVAL;
3642 goto exit;
3643 }
3644 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003645 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003646 ret = -ENOSYS;
3647 goto exit;
3648 }
3649 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3650 if (out->pcm_device_id < 0) {
3651 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3652 __func__, out->pcm_device_id, out->usecase);
3653 ret = -EINVAL;
3654 goto exit;
3655 }
Phil Burkbc991042017-02-24 08:06:44 -08003656
3657 adjust_mmap_period_count(&out->config, min_size_frames);
3658
Eric Laurent0e46adf2016-12-16 12:49:24 -08003659 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3660 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3661 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3662 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3663 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3664 step = "open";
3665 ret = -ENODEV;
3666 goto exit;
3667 }
3668 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3669 if (ret < 0) {
3670 step = "begin";
3671 goto exit;
3672 }
3673 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003674 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003675 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003676 ret = platform_get_mmap_data_fd(adev->platform,
3677 out->pcm_device_id, 0 /*playback*/,
3678 &info->shared_memory_fd,
3679 &mmap_size);
3680 if (ret < 0) {
3681 // Fall back to non exclusive mode
3682 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3683 } else {
3684 if (mmap_size < buffer_size) {
3685 step = "mmap";
3686 goto exit;
3687 }
3688 // FIXME: indicate exclusive mode support by returning a negative buffer size
3689 info->buffer_size_frames *= -1;
3690 }
3691 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003692
3693 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3694 if (ret < 0) {
3695 step = "commit";
3696 goto exit;
3697 }
Phil Burkbc991042017-02-24 08:06:44 -08003698
3699 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003700 ret = 0;
3701
3702 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3703 __func__, info->shared_memory_address, info->buffer_size_frames);
3704
3705exit:
3706 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003707 if (out->pcm == NULL) {
3708 ALOGE("%s: %s - %d", __func__, step, ret);
3709 } else {
3710 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003711 pcm_close(out->pcm);
3712 out->pcm = NULL;
3713 }
3714 }
3715 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003716 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003717 return ret;
3718}
3719
3720static int out_get_mmap_position(const struct audio_stream_out *stream,
3721 struct audio_mmap_position *position)
3722{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003723 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003724 struct stream_out *out = (struct stream_out *)stream;
3725 ALOGVV("%s", __func__);
3726 if (position == NULL) {
3727 return -EINVAL;
3728 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003729 lock_output_stream(out);
3730 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3731 out->pcm == NULL) {
3732 ret = -ENOSYS;
3733 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003734 }
3735
3736 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003737 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003738 if (ret < 0) {
3739 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003740 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003741 }
Andy Hungfc044e12017-03-20 09:24:22 -07003742 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003743exit:
3744 pthread_mutex_unlock(&out->lock);
3745 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003746}
3747
3748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749/** audio_stream_in implementation **/
3750static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3751{
3752 struct stream_in *in = (struct stream_in *)stream;
3753
3754 return in->config.rate;
3755}
3756
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003757static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758{
3759 return -ENOSYS;
3760}
3761
3762static size_t in_get_buffer_size(const struct audio_stream *stream)
3763{
3764 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003765 return in->config.period_size * in->af_period_multiplier *
3766 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767}
3768
3769static uint32_t in_get_channels(const struct audio_stream *stream)
3770{
3771 struct stream_in *in = (struct stream_in *)stream;
3772
3773 return in->channel_mask;
3774}
3775
vivek mehta4ed66e62016-04-15 23:33:34 -07003776static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777{
vivek mehta4ed66e62016-04-15 23:33:34 -07003778 struct stream_in *in = (struct stream_in *)stream;
3779 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780}
3781
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003782static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783{
3784 return -ENOSYS;
3785}
3786
3787static int in_standby(struct audio_stream *stream)
3788{
3789 struct stream_in *in = (struct stream_in *)stream;
3790 struct audio_device *adev = in->dev;
3791 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003792 bool do_stop = true;
3793
Eric Laurent994a6932013-07-17 11:51:42 -07003794 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003795
3796 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003797
3798 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003799 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003800 audio_extn_sound_trigger_stop_lab(in);
3801 in->standby = true;
3802 }
3803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003805 if (adev->adm_deregister_stream)
3806 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3807
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003808 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003810 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003811 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003812 in->capture_started = false;
3813 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003814 if (in->pcm) {
3815 pcm_close(in->pcm);
3816 in->pcm = NULL;
3817 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003818 adev->enable_voicerx = false;
3819 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003820 if (do_stop) {
3821 status = stop_input_stream(in);
3822 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003823 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 }
3825 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003826 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 return status;
3828}
3829
Andy Hungd13f0d32017-06-12 13:58:37 -07003830static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831{
Andy Hungd13f0d32017-06-12 13:58:37 -07003832 struct stream_in *in = (struct stream_in *)stream;
3833
3834 // We try to get the lock for consistency,
3835 // but it isn't necessary for these variables.
3836 // If we're not in standby, we may be blocked on a read.
3837 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3838 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3839 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3840 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3841
3842 if (locked) {
3843 pthread_mutex_unlock(&in->lock);
3844 }
3845
3846 // dump error info
3847 (void)error_log_dump(
3848 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 return 0;
3850}
3851
3852static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3853{
3854 struct stream_in *in = (struct stream_in *)stream;
3855 struct audio_device *adev = in->dev;
3856 struct str_parms *parms;
3857 char *str;
3858 char value[32];
3859 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003860 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861
Eric Laurent994a6932013-07-17 11:51:42 -07003862 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 parms = str_parms_create_str(kvpairs);
3864
3865 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3866
Eric Laurenta1478072015-09-21 17:21:52 -07003867 lock_input_stream(in);
3868
Eric Laurent150dbfe2013-02-27 14:31:02 -08003869 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 if (ret >= 0) {
3871 val = atoi(value);
3872 /* no audio source uses val == 0 */
3873 if ((in->source != val) && (val != 0)) {
3874 in->source = val;
3875 }
3876 }
3877
3878 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880 if (ret >= 0) {
3881 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003882 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003883
3884 // Workaround: If routing to an non existing usb device, fail gracefully
3885 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003886 int card;
3887 if (audio_is_usb_in_device(val) &&
3888 (card = get_alive_usb_card(parms)) >= 0) {
3889
3890 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003891 status = -ENOSYS;
3892 } else {
3893
3894 in->device = val;
3895 /* If recording is in progress, change the tx device to new device */
3896 if (!in->standby) {
3897 ALOGV("update input routing change");
3898 // inform adm before actual routing to prevent glitches.
3899 if (adev->adm_on_routing_change) {
3900 adev->adm_on_routing_change(adev->adm_data,
3901 in->capture_handle);
3902 }
3903 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003904 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003905 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906 }
3907 }
3908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003910 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911
3912 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003913 ALOGV("%s: exit: status(%d)", __func__, status);
3914 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915}
3916
Haynes Mathew George569b7482017-05-08 14:44:27 -07003917static char* in_get_parameters(const struct audio_stream *stream,
3918 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003920 struct stream_in *in = (struct stream_in *)stream;
3921 struct str_parms *query = str_parms_create_str(keys);
3922 char *str;
3923 struct str_parms *reply = str_parms_create();
3924 bool replied = false;
3925
3926 ALOGV("%s: enter: keys - %s", __func__, keys);
3927 replied |= stream_get_parameter_channels(query, reply,
3928 &in->supported_channel_masks[0]);
3929 replied |= stream_get_parameter_formats(query, reply,
3930 &in->supported_formats[0]);
3931 replied |= stream_get_parameter_rates(query, reply,
3932 &in->supported_sample_rates[0]);
3933 if (replied) {
3934 str = str_parms_to_str(reply);
3935 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003936 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003937 }
3938 str_parms_destroy(query);
3939 str_parms_destroy(reply);
3940 ALOGV("%s: exit: returns - %s", __func__, str);
3941 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942}
3943
Eric Laurent51f3c662018-04-10 18:21:34 -07003944static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003945{
Eric Laurent51f3c662018-04-10 18:21:34 -07003946 struct stream_in *in = (struct stream_in *)stream;
3947 char mixer_ctl_name[128];
3948 struct mixer_ctl *ctl;
3949 int ctl_value;
3950
3951 ALOGV("%s: gain %f", __func__, gain);
3952
3953 if (stream == NULL)
3954 return -EINVAL;
3955
3956 /* in_set_gain() only used to silence MMAP capture for now */
3957 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
3958 return -ENOSYS;
3959
3960 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
3961
3962 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
3963 if (!ctl) {
3964 ALOGW("%s: Could not get ctl for mixer cmd - %s",
3965 __func__, mixer_ctl_name);
3966 return -ENOSYS;
3967 }
3968
3969 if (gain < RECORD_GAIN_MIN)
3970 gain = RECORD_GAIN_MIN;
3971 else if (gain > RECORD_GAIN_MAX)
3972 gain = RECORD_GAIN_MAX;
3973 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
3974
3975 mixer_ctl_set_value(ctl, 0, ctl_value);
3976 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003977}
3978
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003979static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3980{
3981 if (!stream || !parms)
3982 return;
3983
3984 struct stream_in *in = (struct stream_in *)stream;
3985 struct audio_device *adev = in->dev;
3986
3987 card_status_t status;
3988 int card;
3989 if (parse_snd_card_status(parms, &card, &status) < 0)
3990 return;
3991
3992 pthread_mutex_lock(&adev->lock);
3993 bool valid_cb = (card == adev->snd_card);
3994 pthread_mutex_unlock(&adev->lock);
3995
3996 if (!valid_cb)
3997 return;
3998
3999 lock_input_stream(in);
4000 if (in->card_status != status)
4001 in->card_status = status;
4002 pthread_mutex_unlock(&in->lock);
4003
4004 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4005 use_case_table[in->usecase],
4006 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4007
4008 // a better solution would be to report error back to AF and let
4009 // it put the stream to standby
4010 if (status == CARD_STATUS_OFFLINE)
4011 in_standby(&in->stream.common);
4012
4013 return;
4014}
4015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4017 size_t bytes)
4018{
4019 struct stream_in *in = (struct stream_in *)stream;
4020 struct audio_device *adev = in->dev;
4021 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004022 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004023 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024
Eric Laurenta1478072015-09-21 17:21:52 -07004025 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004026 const size_t frame_size = audio_stream_in_frame_size(stream);
4027 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004028
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004029 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004030 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004031 /* Read from sound trigger HAL */
4032 audio_extn_sound_trigger_read(in, buffer, bytes);
4033 pthread_mutex_unlock(&in->lock);
4034 return bytes;
4035 }
4036
Eric Laurent0e46adf2016-12-16 12:49:24 -08004037 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4038 ret = -ENOSYS;
4039 goto exit;
4040 }
4041
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004043 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004045 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004047 goto exit;
4048 }
4049 in->standby = 0;
4050 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051
Andy Hungd13f0d32017-06-12 13:58:37 -07004052 // errors that occur here are read errors.
4053 error_code = ERROR_CODE_READ;
4054
Haynes Mathew George03c40102016-01-29 17:57:48 -08004055 //what's the duration requested by the client?
4056 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4057 in->config.rate;
4058 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004059
Haynes Mathew George03c40102016-01-29 17:57:48 -08004060 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004062 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004063 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004064 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004065 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004066 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004067 if (ret < 0) {
4068 ALOGE("Failed to read w/err %s", strerror(errno));
4069 ret = -errno;
4070 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004071 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4072 if (bytes % 4 == 0) {
4073 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4074 int_buf_stream = buffer;
4075 for (size_t itt=0; itt < bytes/4 ; itt++) {
4076 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004077 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004078 } else {
4079 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4080 ret = -EINVAL;
4081 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004082 }
4083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 }
4085
Haynes Mathew George03c40102016-01-29 17:57:48 -08004086 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 /*
4089 * Instead of writing zeroes here, we could trust the hardware
4090 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004091 * 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 -08004092 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004093 if (ret == 0 && adev->mic_muted &&
4094 !voice_is_in_call_rec_stream(in) &&
4095 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004097 in->frames_muted += frames;
4098 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
4100exit:
4101 pthread_mutex_unlock(&in->lock);
4102
4103 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004104 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 in_standby(&in->stream.common);
4106 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004107 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004108 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004109 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004110 }
4111 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004112 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113 }
4114 return bytes;
4115}
4116
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004117static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118{
4119 return 0;
4120}
4121
Andy Hung6ebe5962016-01-15 17:46:57 -08004122static int in_get_capture_position(const struct audio_stream_in *stream,
4123 int64_t *frames, int64_t *time)
4124{
4125 if (stream == NULL || frames == NULL || time == NULL) {
4126 return -EINVAL;
4127 }
4128 struct stream_in *in = (struct stream_in *)stream;
4129 int ret = -ENOSYS;
4130
4131 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004132 // note: ST sessions do not close the alsa pcm driver synchronously
4133 // on standby. Therefore, we may return an error even though the
4134 // pcm stream is still opened.
4135 if (in->standby) {
4136 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4137 "%s stream in standby but pcm not NULL for non ST session", __func__);
4138 goto exit;
4139 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004140 if (in->pcm) {
4141 struct timespec timestamp;
4142 unsigned int avail;
4143 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4144 *frames = in->frames_read + avail;
4145 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4146 ret = 0;
4147 }
4148 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004149exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004150 pthread_mutex_unlock(&in->lock);
4151 return ret;
4152}
4153
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004154static int add_remove_audio_effect(const struct audio_stream *stream,
4155 effect_handle_t effect,
4156 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004158 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004159 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004160 int status = 0;
4161 effect_descriptor_t desc;
4162
4163 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004164 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4165
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004166 if (status != 0)
4167 return status;
4168
Eric Laurenta1478072015-09-21 17:21:52 -07004169 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004170 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004171 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004172 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004173 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004174 in->enable_aec != enable &&
4175 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4176 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004177 if (!enable)
4178 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004179 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4180 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4181 adev->enable_voicerx = enable;
4182 struct audio_usecase *usecase;
4183 struct listnode *node;
4184 list_for_each(node, &adev->usecase_list) {
4185 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004186 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004187 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004188 }
4189 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004190 if (!in->standby
4191 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004192 select_devices(in->dev, in->usecase);
4193 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004194 if (in->enable_ns != enable &&
4195 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4196 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004197 if (!in->standby) {
4198 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4199 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4200 select_devices(in->dev, in->usecase);
4201 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004202 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004203 pthread_mutex_unlock(&in->dev->lock);
4204 pthread_mutex_unlock(&in->lock);
4205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 return 0;
4207}
4208
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004209static int in_add_audio_effect(const struct audio_stream *stream,
4210 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211{
Eric Laurent994a6932013-07-17 11:51:42 -07004212 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004213 return add_remove_audio_effect(stream, effect, true);
4214}
4215
4216static int in_remove_audio_effect(const struct audio_stream *stream,
4217 effect_handle_t effect)
4218{
Eric Laurent994a6932013-07-17 11:51:42 -07004219 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004220 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221}
4222
Eric Laurent0e46adf2016-12-16 12:49:24 -08004223static int in_stop(const struct audio_stream_in* stream)
4224{
4225 struct stream_in *in = (struct stream_in *)stream;
4226 struct audio_device *adev = in->dev;
4227
4228 int ret = -ENOSYS;
4229 ALOGV("%s", __func__);
4230 pthread_mutex_lock(&adev->lock);
4231 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4232 in->capture_started && in->pcm != NULL) {
4233 pcm_stop(in->pcm);
4234 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004235 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004236 }
4237 pthread_mutex_unlock(&adev->lock);
4238 return ret;
4239}
4240
4241static int in_start(const struct audio_stream_in* stream)
4242{
4243 struct stream_in *in = (struct stream_in *)stream;
4244 struct audio_device *adev = in->dev;
4245 int ret = -ENOSYS;
4246
4247 ALOGV("%s in %p", __func__, in);
4248 pthread_mutex_lock(&adev->lock);
4249 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4250 !in->capture_started && in->pcm != NULL) {
4251 if (!in->capture_started) {
4252 ret = start_input_stream(in);
4253 if (ret == 0) {
4254 in->capture_started = true;
4255 }
4256 }
4257 }
4258 pthread_mutex_unlock(&adev->lock);
4259 return ret;
4260}
4261
4262static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4263 int32_t min_size_frames,
4264 struct audio_mmap_buffer_info *info)
4265{
4266 struct stream_in *in = (struct stream_in *)stream;
4267 struct audio_device *adev = in->dev;
4268 int ret = 0;
4269 unsigned int offset1;
4270 unsigned int frames1;
4271 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004272 uint32_t mmap_size;
4273 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004274
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004275 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004276 pthread_mutex_lock(&adev->lock);
4277 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004278
Eric Laurent0e46adf2016-12-16 12:49:24 -08004279 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004280 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004281 ret = -EINVAL;
4282 goto exit;
4283 }
4284 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004285 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004286 ALOGV("%s in %p", __func__, in);
4287 ret = -ENOSYS;
4288 goto exit;
4289 }
4290 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4291 if (in->pcm_device_id < 0) {
4292 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4293 __func__, in->pcm_device_id, in->usecase);
4294 ret = -EINVAL;
4295 goto exit;
4296 }
Phil Burkbc991042017-02-24 08:06:44 -08004297
4298 adjust_mmap_period_count(&in->config, min_size_frames);
4299
Eric Laurent0e46adf2016-12-16 12:49:24 -08004300 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4301 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4302 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4303 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4304 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4305 step = "open";
4306 ret = -ENODEV;
4307 goto exit;
4308 }
4309
4310 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4311 if (ret < 0) {
4312 step = "begin";
4313 goto exit;
4314 }
4315 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004316 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004317 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004318 ret = platform_get_mmap_data_fd(adev->platform,
4319 in->pcm_device_id, 1 /*capture*/,
4320 &info->shared_memory_fd,
4321 &mmap_size);
4322 if (ret < 0) {
4323 // Fall back to non exclusive mode
4324 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4325 } else {
4326 if (mmap_size < buffer_size) {
4327 step = "mmap";
4328 goto exit;
4329 }
4330 // FIXME: indicate exclusive mode support by returning a negative buffer size
4331 info->buffer_size_frames *= -1;
4332 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004333
Haynes Mathew George96483a22017-03-28 14:52:47 -07004334 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004335
4336 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4337 if (ret < 0) {
4338 step = "commit";
4339 goto exit;
4340 }
4341
Phil Burkbc991042017-02-24 08:06:44 -08004342 in->standby = false;
4343 ret = 0;
4344
Eric Laurent0e46adf2016-12-16 12:49:24 -08004345 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4346 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004347
4348exit:
4349 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004350 if (in->pcm == NULL) {
4351 ALOGE("%s: %s - %d", __func__, step, ret);
4352 } else {
4353 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004354 pcm_close(in->pcm);
4355 in->pcm = NULL;
4356 }
4357 }
4358 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004359 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004360 return ret;
4361}
4362
4363static int in_get_mmap_position(const struct audio_stream_in *stream,
4364 struct audio_mmap_position *position)
4365{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004366 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004367 struct stream_in *in = (struct stream_in *)stream;
4368 ALOGVV("%s", __func__);
4369 if (position == NULL) {
4370 return -EINVAL;
4371 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004372 lock_input_stream(in);
4373 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4374 in->pcm == NULL) {
4375 ret = -ENOSYS;
4376 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004377 }
4378 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004379 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004380 if (ret < 0) {
4381 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004382 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004383 }
Andy Hungfc044e12017-03-20 09:24:22 -07004384 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004385exit:
4386 pthread_mutex_unlock(&in->lock);
4387 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004388}
4389
jiabin8962a4d2018-03-19 18:21:24 -07004390static int in_get_active_microphones(const struct audio_stream_in *stream,
4391 struct audio_microphone_characteristic_t *mic_array,
4392 size_t *mic_count) {
4393 struct stream_in *in = (struct stream_in *)stream;
4394 struct audio_device *adev = in->dev;
4395 ALOGVV("%s", __func__);
4396
4397 lock_input_stream(in);
4398 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004399 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004400 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004401 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004402 pthread_mutex_unlock(&adev->lock);
4403 pthread_mutex_unlock(&in->lock);
4404
4405 return ret;
4406}
4407
4408static int adev_get_microphones(const struct audio_hw_device *dev,
4409 struct audio_microphone_characteristic_t *mic_array,
4410 size_t *mic_count) {
4411 struct audio_device *adev = (struct audio_device *)dev;
4412 ALOGVV("%s", __func__);
4413
4414 pthread_mutex_lock(&adev->lock);
4415 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4416 pthread_mutex_unlock(&adev->lock);
4417
4418 return ret;
4419}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004420
Paul McLean57530d52018-12-17 08:24:21 -07004421static int in_set_microphone_direction(const struct audio_stream_in *stream,
4422 audio_microphone_direction_t dir) {
4423 (void)stream;
4424 (void)dir;
4425 ALOGVV("%s", __func__);
4426 return -ENOSYS;
4427}
4428
4429static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
4430 (void)stream;
4431 (void)zoom;
4432 ALOGVV("%s", __func__);
4433 return -ENOSYS;
4434}
4435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436static int adev_open_output_stream(struct audio_hw_device *dev,
4437 audio_io_handle_t handle,
4438 audio_devices_t devices,
4439 audio_output_flags_t flags,
4440 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004441 struct audio_stream_out **stream_out,
4442 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443{
4444 struct audio_device *adev = (struct audio_device *)dev;
4445 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004446 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004447 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4448 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4449 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450
Andy Hungd9653bd2017-08-01 19:31:39 -07004451 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4452 return -ENOSYS;
4453 }
4454
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004455 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4456 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 *stream_out = NULL;
4458 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4459
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004460 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462 if (devices == AUDIO_DEVICE_NONE)
4463 devices = AUDIO_DEVICE_OUT_SPEAKER;
4464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 out->flags = flags;
4466 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004467 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004468 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004469 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004470
4471 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004472 if ((is_hdmi || is_usb_dev) &&
4473 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4474 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4475 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004476 audio_format_t req_format = config->format;
4477 audio_channel_mask_t req_channel_mask = config->channel_mask;
4478 uint32_t req_sample_rate = config->sample_rate;
4479
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004480 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004481 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004482 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004483 if (config->sample_rate == 0)
4484 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004485 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004486 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4487 if (config->format == AUDIO_FORMAT_DEFAULT)
4488 config->format = AUDIO_FORMAT_PCM_16_BIT;
4489 } else if (is_usb_dev) {
4490 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4491 &config->format,
4492 &out->supported_formats[0],
4493 MAX_SUPPORTED_FORMATS,
4494 &config->channel_mask,
4495 &out->supported_channel_masks[0],
4496 MAX_SUPPORTED_CHANNEL_MASKS,
4497 &config->sample_rate,
4498 &out->supported_sample_rates[0],
4499 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004500 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004501 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004502 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004503 if (ret != 0) {
4504 // For MMAP NO IRQ, allow conversions in ADSP
4505 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4506 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004507
Eric Laurentab805ee2018-03-30 12:20:38 -07004508 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4509 config->sample_rate = req_sample_rate;
4510 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4511 config->channel_mask = req_channel_mask;
4512 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4513 config->format = req_format;
4514 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004515
Haynes Mathew George569b7482017-05-08 14:44:27 -07004516 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004517 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004518 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004519 if (is_hdmi) {
4520 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4521 out->config = pcm_config_hdmi_multi;
4522 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4523 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4524 out->config = pcm_config_mmap_playback;
4525 out->stream.start = out_start;
4526 out->stream.stop = out_stop;
4527 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4528 out->stream.get_mmap_position = out_get_mmap_position;
4529 } else {
4530 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4531 out->config = pcm_config_hifi;
4532 }
4533
4534 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004535 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004536 if (is_hdmi) {
4537 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4538 audio_bytes_per_sample(out->format));
4539 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004540 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004541 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004542 pthread_mutex_lock(&adev->lock);
4543 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4544 pthread_mutex_unlock(&adev->lock);
4545
4546 // reject offload during card offline to allow
4547 // fallback to s/w paths
4548 if (offline) {
4549 ret = -ENODEV;
4550 goto error_open;
4551 }
4552
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004553 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4554 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4555 ALOGE("%s: Unsupported Offload information", __func__);
4556 ret = -EINVAL;
4557 goto error_open;
4558 }
4559 if (!is_supported_format(config->offload_info.format)) {
4560 ALOGE("%s: Unsupported audio format", __func__);
4561 ret = -EINVAL;
4562 goto error_open;
4563 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004564 out->sample_rate = config->offload_info.sample_rate;
4565 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4566 out->channel_mask = config->offload_info.channel_mask;
4567 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4568 out->channel_mask = config->channel_mask;
4569 else
4570 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4571
4572 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004573
4574 out->compr_config.codec = (struct snd_codec *)
4575 calloc(1, sizeof(struct snd_codec));
4576
4577 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004578
4579 out->stream.set_callback = out_set_callback;
4580 out->stream.pause = out_pause;
4581 out->stream.resume = out_resume;
4582 out->stream.drain = out_drain;
4583 out->stream.flush = out_flush;
4584
4585 out->compr_config.codec->id =
4586 get_snd_codec_id(config->offload_info.format);
4587 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4588 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004589 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004590 out->compr_config.codec->bit_rate =
4591 config->offload_info.bit_rate;
4592 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004593 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004594 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4595
4596 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4597 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004598
4599 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004600 create_offload_callback_thread(out);
4601 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4602 __func__, config->offload_info.version,
4603 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004604 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4605 switch (config->sample_rate) {
4606 case 0:
4607 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4608 break;
4609 case 8000:
4610 case 16000:
4611 case 48000:
4612 out->sample_rate = config->sample_rate;
4613 break;
4614 default:
4615 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4616 config->sample_rate);
4617 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4618 ret = -EINVAL;
4619 goto error_open;
4620 }
4621 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4622 switch (config->channel_mask) {
4623 case AUDIO_CHANNEL_NONE:
4624 case AUDIO_CHANNEL_OUT_STEREO:
4625 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4626 break;
4627 default:
4628 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4629 config->channel_mask);
4630 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4631 ret = -EINVAL;
4632 goto error_open;
4633 }
4634 switch (config->format) {
4635 case AUDIO_FORMAT_DEFAULT:
4636 case AUDIO_FORMAT_PCM_16_BIT:
4637 out->format = AUDIO_FORMAT_PCM_16_BIT;
4638 break;
4639 default:
4640 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4641 config->format);
4642 config->format = AUDIO_FORMAT_PCM_16_BIT;
4643 ret = -EINVAL;
4644 goto error_open;
4645 }
4646
4647 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004648 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004649 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004650 case 0:
4651 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4652 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004653 case 8000:
4654 case 16000:
4655 case 48000:
4656 out->sample_rate = config->sample_rate;
4657 break;
4658 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004659 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4660 config->sample_rate);
4661 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4662 ret = -EINVAL;
4663 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004664 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004665 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4666 switch (config->channel_mask) {
4667 case AUDIO_CHANNEL_NONE:
4668 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4669 break;
4670 case AUDIO_CHANNEL_OUT_STEREO:
4671 out->channel_mask = config->channel_mask;
4672 break;
4673 default:
4674 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4675 config->channel_mask);
4676 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4677 ret = -EINVAL;
4678 break;
4679 }
4680 switch (config->format) {
4681 case AUDIO_FORMAT_DEFAULT:
4682 out->format = AUDIO_FORMAT_PCM_16_BIT;
4683 break;
4684 case AUDIO_FORMAT_PCM_16_BIT:
4685 out->format = config->format;
4686 break;
4687 default:
4688 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4689 config->format);
4690 config->format = AUDIO_FORMAT_PCM_16_BIT;
4691 ret = -EINVAL;
4692 break;
4693 }
4694 if (ret != 0)
4695 goto error_open;
4696
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004697 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4698 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004699 out->config.rate = out->sample_rate;
4700 out->config.channels =
4701 audio_channel_count_from_out_mask(out->channel_mask);
4702 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004703 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004704 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4705 switch (config->sample_rate) {
4706 case 0:
4707 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4708 break;
4709 case 8000:
4710 case 16000:
4711 case 32000:
4712 case 48000:
4713 out->sample_rate = config->sample_rate;
4714 break;
4715 default:
4716 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4717 config->sample_rate);
4718 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4719 ret = -EINVAL;
4720 break;
4721 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004722 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004723 switch (config->channel_mask) {
4724 case AUDIO_CHANNEL_NONE:
4725 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4726 break;
4727 case AUDIO_CHANNEL_OUT_STEREO:
4728 out->channel_mask = config->channel_mask;
4729 break;
4730 default:
4731 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4732 config->channel_mask);
4733 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4734 ret = -EINVAL;
4735 break;
4736 }
4737 switch (config->format) {
4738 case AUDIO_FORMAT_DEFAULT:
4739 out->format = AUDIO_FORMAT_PCM_16_BIT;
4740 break;
4741 case AUDIO_FORMAT_PCM_16_BIT:
4742 out->format = config->format;
4743 break;
4744 default:
4745 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4746 config->format);
4747 config->format = AUDIO_FORMAT_PCM_16_BIT;
4748 ret = -EINVAL;
4749 break;
4750 }
4751 if (ret != 0)
4752 goto error_open;
4753
vivek mehtaa68fea62017-06-08 19:04:02 -07004754 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004755 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4756 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004757 out->config.rate = out->sample_rate;
4758 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004759 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004760 out->sample_rate,
4761 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004762 out->config.channels,
4763 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004764 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004765 out->config.period_size = buffer_size / frame_size;
4766 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4767 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004768 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004769 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004770 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4771 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004772 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004773 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4774 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004775 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004776 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004777 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004778 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004779 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004780 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4781 out->config = pcm_config_mmap_playback;
4782 out->stream.start = out_start;
4783 out->stream.stop = out_stop;
4784 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4785 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004786 } else {
4787 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4788 out->config = pcm_config_low_latency;
4789 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004790
4791 if (config->sample_rate == 0) {
4792 out->sample_rate = out->config.rate;
4793 } else {
4794 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004795 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004796 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4797 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4798 } else {
4799 out->channel_mask = config->channel_mask;
4800 }
4801 if (config->format == AUDIO_FORMAT_DEFAULT)
4802 out->format = audio_format_from_pcm_format(out->config.format);
4803 else if (!audio_is_linear_pcm(config->format)) {
4804 config->format = AUDIO_FORMAT_PCM_16_BIT;
4805 ret = -EINVAL;
4806 goto error_open;
4807 } else {
4808 out->format = config->format;
4809 }
4810
4811 out->config.rate = out->sample_rate;
4812 out->config.channels =
4813 audio_channel_count_from_out_mask(out->channel_mask);
4814 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4815 out->config.format = pcm_format_from_audio_format(out->format);
4816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004817 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004818
4819 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4820 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004821 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004822 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4823 __func__, config->sample_rate, config->format, config->channel_mask);
4824 config->sample_rate = out->sample_rate;
4825 config->format = out->format;
4826 config->channel_mask = out->channel_mask;
4827 ret = -EINVAL;
4828 goto error_open;
4829 }
4830
Andy Hung6fcba9c2014-03-18 11:53:32 -07004831 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4832 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004833
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004834 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004835 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004836 adev->primary_output = out;
4837 else {
4838 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004839 ret = -EEXIST;
4840 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004841 }
4842 }
4843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844 /* Check if this usecase is already existing */
4845 pthread_mutex_lock(&adev->lock);
4846 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4847 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004849 ret = -EEXIST;
4850 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004851 }
4852 pthread_mutex_unlock(&adev->lock);
4853
4854 out->stream.common.get_sample_rate = out_get_sample_rate;
4855 out->stream.common.set_sample_rate = out_set_sample_rate;
4856 out->stream.common.get_buffer_size = out_get_buffer_size;
4857 out->stream.common.get_channels = out_get_channels;
4858 out->stream.common.get_format = out_get_format;
4859 out->stream.common.set_format = out_set_format;
4860 out->stream.common.standby = out_standby;
4861 out->stream.common.dump = out_dump;
4862 out->stream.common.set_parameters = out_set_parameters;
4863 out->stream.common.get_parameters = out_get_parameters;
4864 out->stream.common.add_audio_effect = out_add_audio_effect;
4865 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4866 out->stream.get_latency = out_get_latency;
4867 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004868#ifdef NO_AUDIO_OUT
4869 out->stream.write = out_write_for_no_output;
4870#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004871 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004872#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004873 out->stream.get_render_position = out_get_render_position;
4874 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004875 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876
Eric Laurent0e46adf2016-12-16 12:49:24 -08004877 if (out->realtime)
4878 out->af_period_multiplier = af_period_multiplier;
4879 else
4880 out->af_period_multiplier = 1;
4881
Andy Hung572633e2019-02-19 11:58:24 -08004882 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
4883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004884 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004885 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004886 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004888 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004889 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004890 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 config->format = out->stream.common.get_format(&out->stream.common);
4893 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4894 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4895
Kevin Rocarda325aa22018-04-03 09:15:52 -07004896 register_format(out->format, out->supported_formats);
4897 register_channel_mask(out->channel_mask, out->supported_channel_masks);
4898 register_sample_rate(out->sample_rate, out->supported_sample_rates);
4899
Andy Hunga452b0a2017-03-15 14:51:15 -07004900 out->error_log = error_log_create(
4901 ERROR_LOG_ENTRIES,
4902 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4903
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004904 /*
4905 By locking output stream before registering, we allow the callback
4906 to update stream's state only after stream's initial state is set to
4907 adev state.
4908 */
4909 lock_output_stream(out);
4910 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4911 pthread_mutex_lock(&adev->lock);
4912 out->card_status = adev->card_status;
4913 pthread_mutex_unlock(&adev->lock);
4914 pthread_mutex_unlock(&out->lock);
4915
vivek mehta4a824772017-06-08 19:05:49 -07004916 stream_app_type_cfg_init(&out->app_type_cfg);
4917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004918 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004919
Eric Laurent994a6932013-07-17 11:51:42 -07004920 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004921 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004922
4923error_open:
4924 free(out);
4925 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004926 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004927 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928}
4929
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004930static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004931 struct audio_stream_out *stream)
4932{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004933 struct stream_out *out = (struct stream_out *)stream;
4934 struct audio_device *adev = out->dev;
4935
Eric Laurent994a6932013-07-17 11:51:42 -07004936 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004937
4938 // must deregister from sndmonitor first to prevent races
4939 // between the callback and close_stream
4940 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004941 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004942 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4943 destroy_offload_callback_thread(out);
4944
4945 if (out->compr_config.codec != NULL)
4946 free(out->compr_config.codec);
4947 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004948
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004949 out->a2dp_compress_mute = false;
4950
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004951 if (adev->voice_tx_output == out)
4952 adev->voice_tx_output = NULL;
4953
Andy Hunga452b0a2017-03-15 14:51:15 -07004954 error_log_destroy(out->error_log);
4955 out->error_log = NULL;
4956
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004957 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004958 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004959 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004960 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004961 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004962}
4963
4964static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4965{
4966 struct audio_device *adev = (struct audio_device *)dev;
4967 struct str_parms *parms;
4968 char *str;
4969 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004970 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004971 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004972 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07004973 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004974
Joe Onorato188b6222016-03-01 11:02:27 -08004975 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004976
4977 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004978
4979 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004980 status = voice_set_parameters(adev, parms);
4981 if (status != 0) {
4982 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 }
4984
4985 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4986 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004987 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4989 adev->bluetooth_nrec = true;
4990 else
4991 adev->bluetooth_nrec = false;
4992 }
4993
4994 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4995 if (ret >= 0) {
4996 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4997 adev->screen_off = false;
4998 else
4999 adev->screen_off = true;
5000 }
5001
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005002 ret = str_parms_get_int(parms, "rotation", &val);
5003 if (ret >= 0) {
5004 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005005 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005006 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005007 // FIXME: note that the code below assumes that the speakers are in the correct placement
5008 // relative to the user when the device is rotated 90deg from its default rotation. This
5009 // assumption is device-specific, not platform-specific like this code.
5010 case 270:
5011 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005012 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005013 break;
5014 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005015 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005016 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5017 break;
5018 case 90:
5019 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005020 break;
5021 default:
5022 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005023 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005024 }
Eric Laurent03f09432014-03-25 18:09:11 -07005025 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005026 // check and set swap
5027 // - check if orientation changed and speaker active
5028 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005029 adev->camera_orientation =
5030 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5031#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005032 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005033#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005034 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005035 }
5036
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005037 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5038 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005039 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005040 }
5041
David Linee3fe402017-03-13 10:00:42 -07005042 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5043 if (ret >= 0) {
5044 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005045 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005046 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5047 if (ret >= 0) {
5048 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005049 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005050 }
Eric Laurent99dab492017-06-17 15:19:08 -07005051 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005052 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5053 if (ret >= 0) {
5054 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005055 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005056 }
5057 }
5058 }
5059
5060 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5061 if (ret >= 0) {
5062 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005063 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005064 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5065 if (ret >= 0) {
5066 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005067 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005068 }
Eric Laurent99dab492017-06-17 15:19:08 -07005069 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005070 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5071 if (ret >= 0) {
5072 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005073 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005074 }
5075 }
5076 }
5077
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005078 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005079 audio_extn_ma_set_parameters(adev, parms);
5080
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005081 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5082 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005083 struct audio_usecase *usecase;
5084 struct listnode *node;
5085 list_for_each(node, &adev->usecase_list) {
5086 usecase = node_to_item(node, struct audio_usecase, list);
5087 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005088 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005089 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5090
5091 pthread_mutex_unlock(&adev->lock);
5092 lock_output_stream(usecase->stream.out);
5093 pthread_mutex_lock(&adev->lock);
5094 audio_extn_a2dp_set_handoff_mode(true);
5095 // force device switch to reconfigure encoder
5096 select_devices(adev, usecase->id);
5097 audio_extn_a2dp_set_handoff_mode(false);
5098 pthread_mutex_unlock(&usecase->stream.out->lock);
5099 break;
5100 }
5101 }
5102 }
5103
Eric Laurent5f4ca952018-10-19 17:33:43 -07005104 //FIXME: to be replaced by proper video capture properties API
5105 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5106 if (ret >= 0) {
5107 int camera_facing = CAMERA_FACING_BACK;
5108 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5109 camera_facing = CAMERA_FACING_FRONT;
5110 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5111 camera_facing = CAMERA_FACING_BACK;
5112 else {
5113 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5114 goto done;
5115 }
5116 adev->camera_orientation =
5117 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5118 struct audio_usecase *usecase;
5119 struct listnode *node;
5120 list_for_each(node, &adev->usecase_list) {
5121 usecase = node_to_item(node, struct audio_usecase, list);
5122 struct stream_in *in = usecase->stream.in;
5123 if (usecase->type == PCM_CAPTURE && in != NULL &&
5124 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5125 select_devices(adev, in->usecase);
5126 }
5127 }
5128 }
5129
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005130done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005131 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005132 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005133 ALOGV("%s: exit with code(%d)", __func__, status);
5134 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005135}
5136
5137static char* adev_get_parameters(const struct audio_hw_device *dev,
5138 const char *keys)
5139{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005140 struct audio_device *adev = (struct audio_device *)dev;
5141 struct str_parms *reply = str_parms_create();
5142 struct str_parms *query = str_parms_create_str(keys);
5143 char *str;
5144
5145 pthread_mutex_lock(&adev->lock);
5146
5147 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005148 audio_extn_a2dp_get_parameters(query, reply);
5149
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005150 str = str_parms_to_str(reply);
5151 str_parms_destroy(query);
5152 str_parms_destroy(reply);
5153
5154 pthread_mutex_unlock(&adev->lock);
5155 ALOGV("%s: exit: returns - %s", __func__, str);
5156 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005157}
5158
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005159static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005160{
5161 return 0;
5162}
5163
Haynes Mathew George5191a852013-09-11 14:19:36 -07005164static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5165{
5166 int ret;
5167 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005168
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005169 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5170
Haynes Mathew George5191a852013-09-11 14:19:36 -07005171 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005172 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005173 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005174
Haynes Mathew George5191a852013-09-11 14:19:36 -07005175 return ret;
5176}
5177
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005178static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179{
5180 return -ENOSYS;
5181}
5182
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005183static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5184 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005185{
5186 return -ENOSYS;
5187}
5188
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005189static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005190{
5191 return -ENOSYS;
5192}
5193
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005194static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195{
5196 return -ENOSYS;
5197}
5198
5199static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5200{
5201 struct audio_device *adev = (struct audio_device *)dev;
5202
5203 pthread_mutex_lock(&adev->lock);
5204 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005205 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005206 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005207 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5208 voice_is_in_call(adev)) {
5209 voice_stop_call(adev);
5210 adev->current_call_output = NULL;
5211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 }
5213 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005214
5215 audio_extn_extspk_set_mode(adev->extspk, mode);
5216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217 return 0;
5218}
5219
5220static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5221{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005222 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005224
Eric Laurent2bafff12016-03-17 12:17:23 -07005225 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005226 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005227 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5228 ret = audio_extn_hfp_set_mic_mute(adev, state);
5229 } else {
5230 ret = voice_set_mic_mute(adev, state);
5231 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005232 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005233 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005234
5235 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005236}
5237
5238static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5239{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005240 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 return 0;
5242}
5243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005244static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 const struct audio_config *config)
5246{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005247 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005248
Eric Laurent74b55762017-07-09 17:04:53 -07005249 /* Don't know if USB HIFI in this context so use true to be conservative */
5250 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5251 true /*is_usb_hifi */) != 0)
5252 return 0;
5253
vivek mehtaa68fea62017-06-08 19:04:02 -07005254 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5255 config->sample_rate, config->format,
5256 channel_count,
5257 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258}
5259
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005260static bool adev_input_allow_hifi_record(struct audio_device *adev,
5261 audio_devices_t devices,
5262 audio_input_flags_t flags,
5263 audio_source_t source) {
5264 const bool allowed = true;
5265
5266 if (!audio_is_usb_in_device(devices))
5267 return !allowed;
5268
5269 switch (flags) {
5270 case AUDIO_INPUT_FLAG_NONE:
5271 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5272 break;
5273 default:
5274 return !allowed;
5275 }
5276
5277 switch (source) {
5278 case AUDIO_SOURCE_DEFAULT:
5279 case AUDIO_SOURCE_MIC:
5280 case AUDIO_SOURCE_UNPROCESSED:
5281 break;
5282 default:
5283 return !allowed;
5284 }
5285
5286 switch (adev->mode) {
5287 case 0:
5288 break;
5289 default:
5290 return !allowed;
5291 }
5292
5293 return allowed;
5294}
5295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005296static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005297 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005298 audio_devices_t devices,
5299 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005300 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005301 audio_input_flags_t flags,
5302 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005303 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005304{
5305 struct audio_device *adev = (struct audio_device *)dev;
5306 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005307 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005308 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005309 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005310 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005311 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5312 devices,
5313 flags,
5314 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005315 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5316 " sample_rate %u, channel_mask %#x, format %#x",
5317 __func__, flags, is_usb_dev, may_use_hifi_record,
5318 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005320
Andy Hungd9653bd2017-08-01 19:31:39 -07005321 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5322 return -ENOSYS;
5323 }
5324
Eric Laurent74b55762017-07-09 17:04:53 -07005325 if (!(is_usb_dev && may_use_hifi_record)) {
5326 if (config->sample_rate == 0)
5327 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5328 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5329 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5330 if (config->format == AUDIO_FORMAT_DEFAULT)
5331 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005332
Eric Laurent74b55762017-07-09 17:04:53 -07005333 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5334
5335 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5336 return -EINVAL;
5337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005339 if (audio_extn_tfa_98xx_is_supported() &&
5340 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005341 return -EINVAL;
5342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005343 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5344
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005345 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005346 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348 in->stream.common.get_sample_rate = in_get_sample_rate;
5349 in->stream.common.set_sample_rate = in_set_sample_rate;
5350 in->stream.common.get_buffer_size = in_get_buffer_size;
5351 in->stream.common.get_channels = in_get_channels;
5352 in->stream.common.get_format = in_get_format;
5353 in->stream.common.set_format = in_set_format;
5354 in->stream.common.standby = in_standby;
5355 in->stream.common.dump = in_dump;
5356 in->stream.common.set_parameters = in_set_parameters;
5357 in->stream.common.get_parameters = in_get_parameters;
5358 in->stream.common.add_audio_effect = in_add_audio_effect;
5359 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5360 in->stream.set_gain = in_set_gain;
5361 in->stream.read = in_read;
5362 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005363 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005364 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005365 in->stream.set_microphone_direction = in_set_microphone_direction;
5366 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
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};