blob: 34fafe7c95487b49e8accd40593b5bbba70c8734 [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"
justinwengc6347db2019-02-21 18:49:00 +080063#include "audio_extn/audiozoom.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070064
Eric Laurent397db572016-05-11 11:31:47 -070065/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
66 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070067#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070068// 2 buffers causes problems with high bitrate files
69#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070/* ToDo: Check and update a proper value in msec */
71#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070072/* treat as unsigned Q1.13 */
73#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070075
76/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070077#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070078
Eric Laurent51f3c662018-04-10 18:21:34 -070079#define RECORD_GAIN_MIN 0.0f
80#define RECORD_GAIN_MAX 1.0f
81#define RECORD_VOLUME_CTL_MAX 0x2000
82
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070083#define PROXY_OPEN_RETRY_COUNT 100
84#define PROXY_OPEN_WAIT_TIME 20
85
vivek mehtadae44712015-07-27 14:13:18 -070086#define MIN_CHANNEL_COUNT 1
87#define DEFAULT_CHANNEL_COUNT 2
88
Jean-Michel Trivic0750692015-10-12 12:12:32 -070089#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
90#define MAX_CHANNEL_COUNT 1
91#else
vivek mehtadae44712015-07-27 14:13:18 -070092#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
93#define XSTR(x) STR(x)
94#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070095#endif
Eric Laurent74b55762017-07-09 17:04:53 -070096#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070097
Haynes Mathew George03c40102016-01-29 17:57:48 -080098#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
99
Glenn Kasten4f993392014-05-14 07:30:48 -0700100static unsigned int configured_low_latency_capture_period_size =
101 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
102
Eric Laurent0e46adf2016-12-16 12:49:24 -0800103
104#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -0800105#define MMAP_PERIOD_COUNT_MIN 32
106#define MMAP_PERIOD_COUNT_MAX 512
107#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800108
Andy Hung31aca912014-03-20 17:14:59 -0700109/* This constant enables extended precision handling.
110 * TODO The flag is off until more testing is done.
111 */
112static const bool k_enable_extended_precision = false;
113
Eric Laurentb23d5282013-05-14 15:27:20 -0700114struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700115 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700116 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
117 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
118 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
121 .stop_threshold = INT_MAX,
122 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
123};
124
125struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700126 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700127 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
128 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
129 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
130 .format = PCM_FORMAT_S16_LE,
131 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
132 .stop_threshold = INT_MAX,
133 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
134};
135
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800136struct pcm_config pcm_config_haptics_audio = {
137 .channels = 1,
138 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
139 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
140 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
141 .format = PCM_FORMAT_S16_LE,
142 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
143 .stop_threshold = INT_MAX,
144 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
145};
146
147struct pcm_config pcm_config_haptics = {
148 .channels = 1,
149 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
150 .period_count = 2,
151 .format = PCM_FORMAT_S16_LE,
152 .stop_threshold = INT_MAX,
153 .avail_min = 0,
154};
155
Haynes Mathew George03c40102016-01-29 17:57:48 -0800156static int af_period_multiplier = 4;
157struct pcm_config pcm_config_rt = {
158 .channels = DEFAULT_CHANNEL_COUNT,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = ULL_PERIOD_SIZE, //1 ms
161 .period_count = 512, //=> buffer size is 512ms
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
164 .stop_threshold = INT_MAX,
165 .silence_threshold = 0,
166 .silence_size = 0,
167 .avail_min = ULL_PERIOD_SIZE, //1 ms
168};
169
Eric Laurentb23d5282013-05-14 15:27:20 -0700170struct pcm_config pcm_config_hdmi_multi = {
171 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
172 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
173 .period_size = HDMI_MULTI_PERIOD_SIZE,
174 .period_count = HDMI_MULTI_PERIOD_COUNT,
175 .format = PCM_FORMAT_S16_LE,
176 .start_threshold = 0,
177 .stop_threshold = INT_MAX,
178 .avail_min = 0,
179};
180
Eric Laurent0e46adf2016-12-16 12:49:24 -0800181struct pcm_config pcm_config_mmap_playback = {
182 .channels = DEFAULT_CHANNEL_COUNT,
183 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
184 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800185 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800186 .format = PCM_FORMAT_S16_LE,
187 .start_threshold = MMAP_PERIOD_SIZE*8,
188 .stop_threshold = INT32_MAX,
189 .silence_threshold = 0,
190 .silence_size = 0,
191 .avail_min = MMAP_PERIOD_SIZE, //1 ms
192};
193
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800194struct pcm_config pcm_config_hifi = {
195 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
196 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
197 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
198 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
199 .format = PCM_FORMAT_S24_3LE,
200 .start_threshold = 0,
201 .stop_threshold = INT_MAX,
202 .avail_min = 0,
203};
204
Eric Laurentb23d5282013-05-14 15:27:20 -0700205struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700206 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700207 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
208 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700209 .stop_threshold = INT_MAX,
210 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700211};
212
Haynes Mathew George03c40102016-01-29 17:57:48 -0800213struct pcm_config pcm_config_audio_capture_rt = {
214 .channels = DEFAULT_CHANNEL_COUNT,
215 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
216 .period_size = ULL_PERIOD_SIZE,
217 .period_count = 512,
218 .format = PCM_FORMAT_S16_LE,
219 .start_threshold = 0,
220 .stop_threshold = INT_MAX,
221 .silence_threshold = 0,
222 .silence_size = 0,
223 .avail_min = ULL_PERIOD_SIZE, //1 ms
224};
225
Eric Laurent0e46adf2016-12-16 12:49:24 -0800226struct pcm_config pcm_config_mmap_capture = {
227 .channels = DEFAULT_CHANNEL_COUNT,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = 0,
233 .stop_threshold = INT_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
vivek mehtaa68fea62017-06-08 19:04:02 -0700239struct pcm_config pcm_config_voip = {
240 .channels = 1,
241 .period_count = 2,
242 .format = PCM_FORMAT_S16_LE,
243 .stop_threshold = INT_MAX,
244 .avail_min = 0,
245};
246
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700247#define AFE_PROXY_CHANNEL_COUNT 2
248#define AFE_PROXY_SAMPLING_RATE 48000
249
jiabinad481a72018-07-23 12:03:17 -0700250#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700251#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
252
253struct pcm_config pcm_config_afe_proxy_playback = {
254 .channels = AFE_PROXY_CHANNEL_COUNT,
255 .rate = AFE_PROXY_SAMPLING_RATE,
256 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
257 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
258 .format = PCM_FORMAT_S16_LE,
259 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
260 .stop_threshold = INT_MAX,
261 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
262};
263
jiabinad481a72018-07-23 12:03:17 -0700264#define AFE_PROXY_RECORD_PERIOD_SIZE 256
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700265#define AFE_PROXY_RECORD_PERIOD_COUNT 4
266
267struct pcm_config pcm_config_afe_proxy_record = {
268 .channels = AFE_PROXY_CHANNEL_COUNT,
269 .rate = AFE_PROXY_SAMPLING_RATE,
270 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
271 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
272 .format = PCM_FORMAT_S16_LE,
273 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
jiabin5d0261e2018-05-25 09:43:59 -0700274 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700275 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
276};
277
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700278const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700279 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
280 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -0800281 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800282 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700283 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700284 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700285 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800286 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700287
Eric Laurentb23d5282013-05-14 15:27:20 -0700288 [USECASE_AUDIO_RECORD] = "audio-record",
289 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800290 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700291 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700292
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800293 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
294 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700295
Eric Laurentb23d5282013-05-14 15:27:20 -0700296 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700297 [USECASE_VOICE2_CALL] = "voice2-call",
298 [USECASE_VOLTE_CALL] = "volte-call",
299 [USECASE_QCHAT_CALL] = "qchat-call",
300 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800301 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
302 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700303
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700304 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
305 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
306
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700307 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
308 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700309
310 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
311 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
312 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
313
vivek mehtaa68fea62017-06-08 19:04:02 -0700314 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
315 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200316
317 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -0700318 [USECASE_INCALL_MUSIC_UPLINK2] = "incall-music-uplink2",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700319
320 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700321};
322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800323
324#define STRING_TO_ENUM(string) { #string, string }
325
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800326struct string_to_enum {
327 const char *name;
328 uint32_t value;
329};
330
Haynes Mathew George569b7482017-05-08 14:44:27 -0700331static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800332 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
333 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
334 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700335 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700336 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700337 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
343 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
344 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
345 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800346};
347
Carter Hsub0c91482019-05-14 18:50:52 +0800348struct in_effect_list {
349 struct listnode list;
350 effect_handle_t handle;
351};
352
Haynes Mathew George5191a852013-09-11 14:19:36 -0700353static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700354static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700355static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700356static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700357//cache last MBDRC cal step level
358static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700359
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800360static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
361static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
362
justinwengc6347db2019-02-21 18:49:00 +0800363static int in_set_microphone_direction(const struct audio_stream_in *stream,
364 audio_microphone_direction_t dir);
365static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
366
Haynes Mathew George03c40102016-01-29 17:57:48 -0800367static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
368 int flags __unused)
369{
370 int dir = 0;
371 switch (uc_id) {
372 case USECASE_AUDIO_RECORD_LOW_LATENCY:
373 dir = 1;
374 case USECASE_AUDIO_PLAYBACK_ULL:
375 break;
376 default:
377 return false;
378 }
379
380 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
381 PCM_PLAYBACK : PCM_CAPTURE);
382 if (adev->adm_is_noirq_avail)
383 return adev->adm_is_noirq_avail(adev->adm_data,
384 adev->snd_card, dev_id, dir);
385 return false;
386}
387
388static void register_out_stream(struct stream_out *out)
389{
390 struct audio_device *adev = out->dev;
391 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
392 return;
393
394 if (!adev->adm_register_output_stream)
395 return;
396
397 adev->adm_register_output_stream(adev->adm_data,
398 out->handle,
399 out->flags);
400
401 if (!adev->adm_set_config)
402 return;
403
404 if (out->realtime) {
405 adev->adm_set_config(adev->adm_data,
406 out->handle,
407 out->pcm, &out->config);
408 }
409}
410
411static void register_in_stream(struct stream_in *in)
412{
413 struct audio_device *adev = in->dev;
414 if (!adev->adm_register_input_stream)
415 return;
416
417 adev->adm_register_input_stream(adev->adm_data,
418 in->capture_handle,
419 in->flags);
420
421 if (!adev->adm_set_config)
422 return;
423
424 if (in->realtime) {
425 adev->adm_set_config(adev->adm_data,
426 in->capture_handle,
427 in->pcm,
428 &in->config);
429 }
430}
431
432static void request_out_focus(struct stream_out *out, long ns)
433{
434 struct audio_device *adev = out->dev;
435
Haynes Mathew George03c40102016-01-29 17:57:48 -0800436 if (adev->adm_request_focus_v2) {
437 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
438 } else if (adev->adm_request_focus) {
439 adev->adm_request_focus(adev->adm_data, out->handle);
440 }
441}
442
443static void request_in_focus(struct stream_in *in, long ns)
444{
445 struct audio_device *adev = in->dev;
446
Haynes Mathew George03c40102016-01-29 17:57:48 -0800447 if (adev->adm_request_focus_v2) {
448 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
449 } else if (adev->adm_request_focus) {
450 adev->adm_request_focus(adev->adm_data, in->capture_handle);
451 }
452}
453
454static void release_out_focus(struct stream_out *out, long ns __unused)
455{
456 struct audio_device *adev = out->dev;
457
458 if (adev->adm_abandon_focus)
459 adev->adm_abandon_focus(adev->adm_data, out->handle);
460}
461
462static void release_in_focus(struct stream_in *in, long ns __unused)
463{
464 struct audio_device *adev = in->dev;
465 if (adev->adm_abandon_focus)
466 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
467}
468
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700469static int parse_snd_card_status(struct str_parms * parms, int * card,
470 card_status_t * status)
471{
472 char value[32]={0};
473 char state[32]={0};
474
475 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
476
477 if (ret < 0)
478 return -1;
479
480 // sscanf should be okay as value is of max length 32.
481 // same as sizeof state.
482 if (sscanf(value, "%d,%s", card, state) < 2)
483 return -1;
484
485 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
486 CARD_STATUS_OFFLINE;
487 return 0;
488}
489
vivek mehta40125092017-08-21 18:48:51 -0700490// always call with adev lock held
491void send_gain_dep_calibration_l() {
492 if (last_known_cal_step >= 0)
493 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
494}
495
vivek mehta1a9b7c02015-06-25 11:49:38 -0700496__attribute__ ((visibility ("default")))
497bool audio_hw_send_gain_dep_calibration(int level) {
498 bool ret_val = false;
499 ALOGV("%s: enter ... ", __func__);
500
501 pthread_mutex_lock(&adev_init_lock);
502
503 if (adev != NULL && adev->platform != NULL) {
504 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700505 last_known_cal_step = level;
506 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700507 pthread_mutex_unlock(&adev->lock);
508 } else {
509 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
510 }
511
512 pthread_mutex_unlock(&adev_init_lock);
513
514 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
515 return ret_val;
516}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700517
jasmine cha270b7762018-03-30 15:41:33 +0800518#ifdef MAXXAUDIO_QDSP_ENABLED
519bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
520{
521 bool ret = false;
522 ALOGV("%s: enter ...", __func__);
523
524 pthread_mutex_lock(&adev_init_lock);
525
526 if (adev != NULL && adev->platform != NULL) {
527 pthread_mutex_lock(&adev->lock);
528 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
529 pthread_mutex_unlock(&adev->lock);
530 }
531
532 pthread_mutex_unlock(&adev_init_lock);
533
534 ALOGV("%s: exit with ret %d", __func__, ret);
535 return ret;
536}
537#else
538#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
539#endif
540
vivek mehtaa8d7c922016-05-25 14:40:44 -0700541__attribute__ ((visibility ("default")))
542int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
543 int table_size) {
544 int ret_val = 0;
545 ALOGV("%s: enter ... ", __func__);
546
547 pthread_mutex_lock(&adev_init_lock);
548 if (adev == NULL) {
549 ALOGW("%s: adev is NULL .... ", __func__);
550 goto done;
551 }
552
553 pthread_mutex_lock(&adev->lock);
554 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
555 pthread_mutex_unlock(&adev->lock);
556done:
557 pthread_mutex_unlock(&adev_init_lock);
558 ALOGV("%s: exit ... ", __func__);
559 return ret_val;
560}
561
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700562static bool is_supported_format(audio_format_t format)
563{
Eric Laurent8251ac82014-07-23 11:00:25 -0700564 switch (format) {
565 case AUDIO_FORMAT_MP3:
566 case AUDIO_FORMAT_AAC_LC:
567 case AUDIO_FORMAT_AAC_HE_V1:
568 case AUDIO_FORMAT_AAC_HE_V2:
569 return true;
570 default:
571 break;
572 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700573 return false;
574}
575
juyuchenbe5c67e2018-08-29 17:19:20 +0800576static bool is_supported_24bits_audiosource(audio_source_t source)
577{
578 switch (source) {
579 case AUDIO_SOURCE_UNPROCESSED:
580#ifdef ENABLED_24BITS_CAMCORDER
581 case AUDIO_SOURCE_CAMCORDER:
582#endif
583 return true;
584 default:
585 break;
586 }
587 return false;
588}
589
Haynes Mathew George03c40102016-01-29 17:57:48 -0800590static inline bool is_mmap_usecase(audio_usecase_t uc_id)
591{
592 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
593 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
594}
595
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700596static int get_snd_codec_id(audio_format_t format)
597{
598 int id = 0;
599
Eric Laurent8251ac82014-07-23 11:00:25 -0700600 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700601 case AUDIO_FORMAT_MP3:
602 id = SND_AUDIOCODEC_MP3;
603 break;
604 case AUDIO_FORMAT_AAC:
605 id = SND_AUDIOCODEC_AAC;
606 break;
607 default:
608 ALOGE("%s: Unsupported audio format", __func__);
609 }
610
611 return id;
612}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800613
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800614static int audio_ssr_status(struct audio_device *adev)
615{
616 int ret = 0;
617 struct mixer_ctl *ctl;
618 const char *mixer_ctl_name = "Audio SSR Status";
619
620 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
621 ret = mixer_ctl_get_value(ctl, 0);
622 ALOGD("%s: value: %d", __func__, ret);
623 return ret;
624}
625
vivek mehta4a824772017-06-08 19:05:49 -0700626static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
627{
628 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
629}
630
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800631static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
632{
633 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
634 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
635 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
636 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
637 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
638 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
639
640}
641
642static bool is_a2dp_device(snd_device_t out_snd_device)
643{
644 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
645}
646
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800647int enable_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);
657
Carter Hsuaaa94962019-05-14 14:26:24 +0800658 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
659
Carter Hsub0c91482019-05-14 18:50:52 +0800660 if (usecase->type == PCM_CAPTURE) {
661 struct stream_in *in = usecase->stream.in;
662 struct audio_usecase *uinfo;
yixuanjiang509f0a72018-09-06 18:37:23 +0800663 snd_device = usecase->in_snd_device;
Carter Hsub0c91482019-05-14 18:50:52 +0800664
665 if (in) {
666 if (in->enable_aec || in->enable_ec_port) {
667 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
668 struct listnode *node;
669 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
670 USECASE_AUDIO_PLAYBACK_VOIP);
671 if (voip_usecase) {
672 out_device = voip_usecase->stream.out->devices;
673 } else if (adev->primary_output &&
674 !adev->primary_output->standby) {
675 out_device = adev->primary_output->devices;
676 } else {
677 list_for_each(node, &adev->usecase_list) {
678 uinfo = node_to_item(node, struct audio_usecase, list);
679 if (uinfo->type != PCM_CAPTURE) {
680 out_device = uinfo->stream.out->devices;
681 break;
682 }
683 }
684 }
685 platform_set_echo_reference(adev, true, out_device);
686 in->ec_opened = true;
687 }
688 }
689 } else
yixuanjiang509f0a72018-09-06 18:37:23 +0800690 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530691 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800692 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800693 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700694
695 // we shouldn't truncate mixer_path
696 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
697 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
698 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800699 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700700
Eric Laurent2e140aa2016-06-30 17:14:46 -0700701 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700702 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704 ALOGV("%s: exit", __func__);
705 return 0;
706}
707
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800708int disable_audio_route(struct audio_device *adev,
709 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800710{
yixuanjiang509f0a72018-09-06 18:37:23 +0800711 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700712 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800713
714 if (usecase == NULL)
715 return -EINVAL;
716
717 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800718 if (usecase->type == PCM_CAPTURE)
719 snd_device = usecase->in_snd_device;
720 else
721 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700722
723 // we shouldn't truncate mixer_path
724 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
725 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
726 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800727 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700728 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700729
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700730 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsub0c91482019-05-14 18:50:52 +0800731 if (usecase->type == PCM_CAPTURE) {
732 struct stream_in *in = usecase->stream.in;
733 if (in && in->ec_opened) {
734 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
735 in->ec_opened = false;
736 }
737 }
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000738 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800740 ALOGV("%s: exit", __func__);
741 return 0;
742}
743
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800744int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700745 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700747 int i, num_devices = 0;
748 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800749 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800750 if (snd_device < SND_DEVICE_MIN ||
751 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800752 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800753 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800754 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700756 platform_send_audio_calibration(adev->platform, snd_device);
757
vivek mehtade4849c2016-03-03 17:23:38 -0800758 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700759 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700760 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800761 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762 }
763
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700764 /* due to the possibility of calibration overwrite between listen
765 and audio, notify sound trigger hal before audio calibration is sent */
766 audio_extn_sound_trigger_update_device_status(snd_device,
767 ST_EVENT_SND_DEVICE_BUSY);
768
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700769 if (audio_extn_spkr_prot_is_enabled())
770 audio_extn_spkr_prot_calib_cancel(adev);
771
zhaoyang yin4211fad2015-06-04 21:13:25 +0800772 audio_extn_dsm_feedback_enable(adev, snd_device, true);
773
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700774 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800775 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800776 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700777 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
778 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700779 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800780 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700781 }
782 if (audio_extn_spkr_prot_start_processing(snd_device)) {
783 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800784 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700785 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700786 } else if (platform_can_split_snd_device(snd_device,
787 &num_devices,
788 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700789 for (i = 0; i < num_devices; i++) {
790 enable_snd_device(adev, new_snd_devices[i]);
791 }
vivek mehtab6506412015-08-07 16:55:17 -0700792 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700793 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800794 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
795 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
796 ALOGE(" %s: Invalid sound device returned", __func__);
797 goto on_error;
798 }
Ed Tam70b5c142016-03-21 19:14:29 -0700799
Eric Laurent2e140aa2016-06-30 17:14:46 -0700800 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700801
802 if (is_a2dp_device(snd_device) &&
803 (audio_extn_a2dp_start_playback() < 0)) {
804 ALOGE("%s: failed to configure A2DP control path", __func__);
805 goto on_error;
806 }
807
vivek mehtade4849c2016-03-03 17:23:38 -0800808 audio_route_apply_and_update_path(adev->audio_route, device_name);
809 }
810on_success:
811 adev->snd_dev_ref_cnt[snd_device]++;
812 ret_val = 0;
813on_error:
814 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815}
816
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800817int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700818 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700820 int i, num_devices = 0;
821 snd_device_t new_snd_devices[2];
822
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800823 if (snd_device < SND_DEVICE_MIN ||
824 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800825 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800826 return -EINVAL;
827 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700828 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
829 ALOGE("%s: device ref cnt is already 0", __func__);
830 return -EINVAL;
831 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800832 audio_extn_tfa_98xx_disable_speaker(snd_device);
833
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 adev->snd_dev_ref_cnt[snd_device]--;
835 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800836 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800837
838 if (is_a2dp_device(snd_device))
839 audio_extn_a2dp_stop_playback();
840
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700841 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800842 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700843 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700844 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
845 audio_extn_spkr_prot_is_enabled()) {
846 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700847
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700848 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
849 // and does not use speaker swap. As this code causes a problem with device enable ref
850 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700851 // when speaker device is disabled, reset swap.
852 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700853 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700854
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700855 } else if (platform_can_split_snd_device(snd_device,
856 &num_devices,
857 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700858 for (i = 0; i < num_devices; i++) {
859 disable_snd_device(adev, new_snd_devices[i]);
860 }
vivek mehtab6506412015-08-07 16:55:17 -0700861 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700862 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800863 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
864 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
865 ALOGE(" %s: Invalid sound device returned", __func__);
866 return -EINVAL;
867 }
868
Eric Laurent2e140aa2016-06-30 17:14:46 -0700869 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800870 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700871 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700872 audio_extn_sound_trigger_update_device_status(snd_device,
873 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 }
vivek mehtab6506412015-08-07 16:55:17 -0700875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800876 return 0;
877}
878
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800879#ifdef DYNAMIC_ECNS_ENABLED
880static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
881 struct stream_in *in,
882 struct audio_effect_config effect_config,
883 unsigned int param_value)
884{
885 char mixer_ctl_name[] = "Audio Effect";
886 long set_values[6];
887
888 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
889 if (!ctl) {
890 ALOGE("%s: Could not get mixer ctl - %s",
891 __func__, mixer_ctl_name);
892 return -EINVAL;
893 }
894
895 set_values[0] = 1; //0:Rx 1:Tx
896 set_values[1] = in->app_type_cfg.app_type;
897 set_values[2] = (long)effect_config.module_id;
898 set_values[3] = (long)effect_config.instance_id;
899 set_values[4] = (long)effect_config.param_id;
900 set_values[5] = param_value;
901
902 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
903
904 return 0;
905
906}
907
908static int update_effect_param_ecns(struct audio_usecase *usecase,
909 unsigned int module_id, int effect_type,
910 unsigned int *param_value)
911{
912 int ret = 0;
913 struct audio_effect_config other_effect_config;
914 struct stream_in *in = NULL;
915
916 if (!usecase)
917 return -EINVAL;
918
919 in = usecase->stream.in;
920
921 /* Get the effect config data of the other effect */
922 ret = platform_get_effect_config_data(usecase->in_snd_device,
923 &other_effect_config,
924 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
925 if (ret < 0) {
926 ALOGE("%s Failed to get effect params %d", __func__, ret);
927 return ret;
928 }
929
930 if (module_id == other_effect_config.module_id) {
931 //Same module id for AEC/NS. Values need to be combined
932 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
933 ((effect_type == EFFECT_NS) && (in->enable_aec)))
934 *param_value |= other_effect_config.param_value;
935 }
936
937 return ret;
938}
939
940static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
941 int effect_type, bool enable)
942{
943 struct audio_effect_config effect_config;
944 struct audio_usecase *usecase = NULL;
945 int ret = 0;
946 unsigned int param_value = 0;
947
948 if (!in) {
949 ALOGE("%s: Invalid input stream", __func__);
950 return -EINVAL;
951 }
952
953 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
954
955 usecase = get_usecase_from_list(adev, in->usecase);
956
957 ret = platform_get_effect_config_data(usecase->in_snd_device,
958 &effect_config, effect_type);
959 if (ret < 0) {
960 ALOGE("%s Failed to get module id %d", __func__, ret);
961 return ret;
962 }
963 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
964 __func__, effect_config.module_id, in->app_type_cfg.app_type,
965 usecase->id, usecase->in_snd_device);
966
967 if (enable)
968 param_value = effect_config.param_value;
969
970 /*Special handling for AEC & NS effects Param values need to be
971 updated if module ids are same*/
972
973 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
974 ret = update_effect_param_ecns(usecase, effect_config.module_id,
975 effect_type, &param_value);
976 if (ret < 0)
977 return ret;
978 }
979
980 ret = send_effect_enable_disable_mixer_ctl(adev, in,
981 effect_config, param_value);
982
983 return ret;
984}
985
986static int check_and_enable_effect(struct audio_device *adev)
987{
988 int ret = 0;
989
990 struct listnode *node;
991 struct stream_in *in = NULL;
992
993 list_for_each(node, &adev->usecase_list)
994 {
995 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
996 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
997 in = usecase->stream.in;
998
999 if (in->standby)
1000 continue;
1001
1002 if (in->enable_aec) {
1003 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
1004 }
1005
1006 if (in->enable_ns &&
1007 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1008 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
1009 }
1010 }
1011 }
1012
1013 return ret;
1014}
1015#else
1016#define enable_disable_effect(w, x, y, z) -ENOSYS
1017#define check_and_enable_effect(x) -ENOSYS
1018#endif
1019
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001020/*
1021 legend:
1022 uc - existing usecase
1023 new_uc - new usecase
1024 d1, d11, d2 - SND_DEVICE enums
1025 a1, a2 - corresponding ANDROID device enums
1026 B, B1, B2 - backend strings
1027
1028case 1
1029 uc->dev d1 (a1) B1
1030 new_uc->dev d1 (a1), d2 (a2) B1, B2
1031
1032 resolution: disable and enable uc->dev on d1
1033
1034case 2
1035 uc->dev d1 (a1) B1
1036 new_uc->dev d11 (a1) B1
1037
1038 resolution: need to switch uc since d1 and d11 are related
1039 (e.g. speaker and voice-speaker)
1040 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1041
1042case 3
1043 uc->dev d1 (a1) B1
1044 new_uc->dev d2 (a2) B2
1045
1046 resolution: no need to switch uc
1047
1048case 4
1049 uc->dev d1 (a1) B
1050 new_uc->dev d2 (a2) B
1051
1052 resolution: disable enable uc-dev on d2 since backends match
1053 we cannot enable two streams on two different devices if they
1054 share the same backend. e.g. if offload is on speaker device using
1055 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1056 using the same backend, offload must also be switched to voice-handset.
1057
1058case 5
1059 uc->dev d1 (a1) B
1060 new_uc->dev d1 (a1), d2 (a2) B
1061
1062 resolution: disable enable uc-dev on d2 since backends match
1063 we cannot enable two streams on two different devices if they
1064 share the same backend.
1065
1066case 6
1067 uc->dev d1 a1 B1
1068 new_uc->dev d2 a1 B2
1069
1070 resolution: no need to switch
1071
1072case 7
1073
1074 uc->dev d1 (a1), d2 (a2) B1, B2
1075 new_uc->dev d1 B1
1076
1077 resolution: no need to switch
1078
1079*/
1080static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1081 struct audio_usecase *new_uc,
1082 snd_device_t new_snd_device)
1083{
1084 audio_devices_t a1 = uc->stream.out->devices;
1085 audio_devices_t a2 = new_uc->stream.out->devices;
1086
1087 snd_device_t d1 = uc->out_snd_device;
1088 snd_device_t d2 = new_snd_device;
1089
1090 // Treat as a special case when a1 and a2 are not disjoint
1091 if ((a1 != a2) && (a1 & a2)) {
1092 snd_device_t d3[2];
1093 int num_devices = 0;
1094 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1095 &num_devices,
1096 d3);
1097 if (ret < 0) {
1098 if (ret != -ENOSYS) {
1099 ALOGW("%s failed to split snd_device %d",
1100 __func__,
1101 popcount(a1) > 1 ? d1 : d2);
1102 }
1103 goto end;
1104 }
1105
1106 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1107 // But if it does happen, we need to give priority to d2 if
1108 // the combo devices active on the existing usecase share a backend.
1109 // This is because we cannot have a usecase active on a combo device
1110 // and a new usecase requests one device in this combo pair.
1111 if (platform_check_backends_match(d3[0], d3[1])) {
1112 return d2; // case 5
1113 } else {
1114 return d1; // case 1
1115 }
1116 } else {
1117 if (platform_check_backends_match(d1, d2)) {
1118 return d2; // case 2, 4
1119 } else {
1120 return d1; // case 6, 3
1121 }
1122 }
1123
1124end:
1125 return d2; // return whatever was calculated before.
1126}
1127
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001128static void check_and_route_playback_usecases(struct audio_device *adev,
1129 struct audio_usecase *uc_info,
1130 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131{
1132 struct listnode *node;
1133 struct audio_usecase *usecase;
1134 bool switch_device[AUDIO_USECASE_MAX];
1135 int i, num_uc_to_switch = 0;
1136
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001137 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1138 uc_info,
1139 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001140
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001141 /* For a2dp device reconfigure all active sessions
1142 * with new AFE encoder format based on a2dp state
1143 */
1144 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001145 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1146 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001147 audio_extn_a2dp_is_force_device_switch()) {
1148 force_routing = true;
1149 }
1150
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151 /*
1152 * This function is to make sure that all the usecases that are active on
1153 * the hardware codec backend are always routed to any one device that is
1154 * handled by the hardware codec.
1155 * For example, if low-latency and deep-buffer usecases are currently active
1156 * on speaker and out_set_parameters(headset) is received on low-latency
1157 * output, then we have to make sure deep-buffer is also switched to headset,
1158 * because of the limitation that both the devices cannot be enabled
1159 * at the same time as they share the same backend.
1160 */
1161 /* Disable all the usecases on the shared backend other than the
1162 specified usecase */
1163 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1164 switch_device[i] = false;
1165
1166 list_for_each(node, &adev->usecase_list) {
1167 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001168 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1169 continue;
1170
1171 if (force_routing ||
1172 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001173 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1174 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001175 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001176 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1177 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001178 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001179 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001180 switch_device[usecase->id] = true;
1181 num_uc_to_switch++;
1182 }
1183 }
1184
1185 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 list_for_each(node, &adev->usecase_list) {
1187 usecase = node_to_item(node, struct audio_usecase, list);
1188 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001189 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001190 }
1191 }
1192
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001193 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001194 list_for_each(node, &adev->usecase_list) {
1195 usecase = node_to_item(node, struct audio_usecase, list);
1196 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001197 d_device = derive_playback_snd_device(usecase, uc_info,
1198 snd_device);
1199 enable_snd_device(adev, d_device);
1200 /* Update the out_snd_device before enabling the audio route */
1201 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 }
1203 }
1204
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001205 /* Re-route all the usecases on the shared backend other than the
1206 specified usecase to new snd devices */
1207 list_for_each(node, &adev->usecase_list) {
1208 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001210 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 }
1212 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001213 }
1214}
1215
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001216static void check_and_route_capture_usecases(struct audio_device *adev,
1217 struct audio_usecase *uc_info,
1218 snd_device_t snd_device)
1219{
1220 struct listnode *node;
1221 struct audio_usecase *usecase;
1222 bool switch_device[AUDIO_USECASE_MAX];
1223 int i, num_uc_to_switch = 0;
1224
vivek mehta4ed66e62016-04-15 23:33:34 -07001225 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1226
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001227 /*
1228 * This function is to make sure that all the active capture usecases
1229 * are always routed to the same input sound device.
1230 * For example, if audio-record and voice-call usecases are currently
1231 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1232 * is received for voice call then we have to make sure that audio-record
1233 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1234 * because of the limitation that two devices cannot be enabled
1235 * at the same time if they share the same backend.
1236 */
1237 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1238 switch_device[i] = false;
1239
1240 list_for_each(node, &adev->usecase_list) {
1241 usecase = node_to_item(node, struct audio_usecase, list);
1242 if (usecase->type != PCM_PLAYBACK &&
1243 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001244 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001245 ((uc_info->type == VOICE_CALL &&
1246 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1247 platform_check_backends_match(snd_device,\
1248 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001249 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001250 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1251 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001252 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001253 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001254 switch_device[usecase->id] = true;
1255 num_uc_to_switch++;
1256 }
1257 }
1258
1259 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001260 list_for_each(node, &adev->usecase_list) {
1261 usecase = node_to_item(node, struct audio_usecase, list);
1262 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001263 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001264 }
1265 }
1266
1267 list_for_each(node, &adev->usecase_list) {
1268 usecase = node_to_item(node, struct audio_usecase, list);
1269 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001270 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001271 }
1272 }
1273
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001274 /* Re-route all the usecases on the shared backend other than the
1275 specified usecase to new snd devices */
1276 list_for_each(node, &adev->usecase_list) {
1277 usecase = node_to_item(node, struct audio_usecase, list);
1278 /* Update the in_snd_device only before enabling the audio route */
1279 if (switch_device[usecase->id] ) {
1280 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001281 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001282 }
1283 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001284 }
1285}
1286
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001287/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001288static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001290 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001291 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001292
1293 switch (channels) {
1294 /*
1295 * Do not handle stereo output in Multi-channel cases
1296 * Stereo case is handled in normal playback path
1297 */
1298 case 6:
1299 ALOGV("%s: HDMI supports 5.1", __func__);
1300 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1301 break;
1302 case 8:
1303 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1304 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1305 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1306 break;
1307 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001308 ALOGE("HDMI does not support multi channel playback");
1309 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 break;
1311 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001312 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001313}
1314
Andy Hung18859412017-08-09 11:47:21 -07001315static ssize_t read_usb_sup_sample_rates(bool is_playback,
1316 uint32_t *supported_sample_rates,
1317 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001318{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001319 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1320 supported_sample_rates,
1321 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001322#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001323 for (ssize_t i=0; i<count; i++) {
1324 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1325 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001326 }
1327#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001328 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001329}
1330
Haynes Mathew George569b7482017-05-08 14:44:27 -07001331static int read_usb_sup_channel_masks(bool is_playback,
1332 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001333 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001334{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001335 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001336 int channel_count;
1337 uint32_t num_masks = 0;
1338 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1339 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001340 }
Eric Laurent74b55762017-07-09 17:04:53 -07001341 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001342 // start from 2 channels as framework currently doesn't support mono.
Eric Laurent154055d2019-05-01 18:07:29 -07001343 if (channels >= FCC_2) {
1344 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
Eric Laurent74b55762017-07-09 17:04:53 -07001345 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001346 for (channel_count = FCC_2;
1347 channel_count <= channels && num_masks < max_masks;
1348 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001349 supported_channel_masks[num_masks++] =
1350 audio_channel_mask_for_index_assignment_from_count(channel_count);
1351 }
1352 } else {
1353 // For capture we report all supported channel masks from 1 channel up.
1354 channel_count = MIN_CHANNEL_COUNT;
1355 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1356 // indexed mask
1357 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Eric Laurent154055d2019-05-01 18:07:29 -07001358 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1359 if (channel_count <= FCC_2) {
1360 mask = audio_channel_in_mask_from_count(channel_count);
1361 supported_channel_masks[num_masks++] = mask;
1362 }
Andy Hung88ce1d92018-10-29 18:31:12 -07001363 const audio_channel_mask_t index_mask =
1364 audio_channel_mask_for_index_assignment_from_count(channel_count);
1365 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1366 supported_channel_masks[num_masks++] = index_mask;
1367 }
Eric Laurent74b55762017-07-09 17:04:53 -07001368 }
1369 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001370#ifdef NDEBUG
1371 for (size_t i = 0; i < num_masks; ++i) {
1372 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1373 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1374 }
1375#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001376 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001377}
1378
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001379static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001380 audio_format_t *supported_formats,
1381 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001382{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001383 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001384 switch (bitwidth) {
1385 case 24:
1386 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001387 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001388 break;
1389 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001390 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001391 break;
1392 case 16:
1393 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001394 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001395 break;
1396 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001397 ALOGV("%s: %s supported format %d", __func__,
1398 is_playback ? "P" : "C", bitwidth);
1399 return 1;
1400}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001401
Haynes Mathew George569b7482017-05-08 14:44:27 -07001402static int read_usb_sup_params_and_compare(bool is_playback,
1403 audio_format_t *format,
1404 audio_format_t *supported_formats,
1405 uint32_t max_formats,
1406 audio_channel_mask_t *mask,
1407 audio_channel_mask_t *supported_channel_masks,
1408 uint32_t max_masks,
1409 uint32_t *rate,
1410 uint32_t *supported_sample_rates,
1411 uint32_t max_rates) {
1412 int ret = 0;
1413 int num_formats;
1414 int num_masks;
1415 int num_rates;
1416 int i;
1417
1418 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1419 max_formats);
1420 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1421 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001422
Haynes Mathew George569b7482017-05-08 14:44:27 -07001423 num_rates = read_usb_sup_sample_rates(is_playback,
1424 supported_sample_rates, max_rates);
1425
1426#define LUT(table, len, what, dflt) \
1427 for (i=0; i<len && (table[i] != what); i++); \
1428 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1429
1430 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1431 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1432 LUT(supported_sample_rates, num_rates, *rate, 0);
1433
1434#undef LUT
1435 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001436}
1437
Andy Hungd9653bd2017-08-01 19:31:39 -07001438static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1439{
1440 // Check if usb is ready.
1441 // The usb device may have been removed quickly after insertion and hence
1442 // no longer available. This will show up as empty channel masks, or rates.
1443
1444 pthread_mutex_lock(&adev->lock);
1445 uint32_t supported_sample_rate;
1446
1447 // we consider usb ready if we can fetch at least one sample rate.
1448 const bool ready = read_usb_sup_sample_rates(
1449 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1450 pthread_mutex_unlock(&adev->lock);
1451 return ready;
1452}
1453
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001454static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1455{
1456 struct audio_usecase *usecase;
1457 struct listnode *node;
1458
1459 list_for_each(node, &adev->usecase_list) {
1460 usecase = node_to_item(node, struct audio_usecase, list);
1461 if (usecase->type == VOICE_CALL) {
1462 ALOGV("%s: usecase id %d", __func__, usecase->id);
1463 return usecase->id;
1464 }
1465 }
1466 return USECASE_INVALID;
1467}
1468
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001469struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1470 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001471{
1472 struct audio_usecase *usecase;
1473 struct listnode *node;
1474
1475 list_for_each(node, &adev->usecase_list) {
1476 usecase = node_to_item(node, struct audio_usecase, list);
1477 if (usecase->id == uc_id)
1478 return usecase;
1479 }
1480 return NULL;
1481}
1482
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001483static bool force_device_switch(struct audio_usecase *usecase)
1484{
Carter Hsuaaa94962019-05-14 14:26:24 +08001485 if (usecase->type == PCM_CAPTURE || usecase->stream.out == NULL) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001486 return false;
1487 }
1488
1489 // Force all A2DP output devices to reconfigure for proper AFE encode format
1490 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1491 // in suspended state, hence try to trigger a retry when we again get a routing request.
1492 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1493 audio_extn_a2dp_is_force_device_switch()) {
1494 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1495 return true;
1496 }
1497
1498 return false;
1499}
1500
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001501struct stream_in *adev_get_active_input(const struct audio_device *adev)
1502{
1503 struct listnode *node;
1504 struct stream_in *last_active_in = NULL;
1505
1506 /* Get last added active input.
1507 * TODO: We may use a priority mechanism to pick highest priority active source */
1508 list_for_each(node, &adev->usecase_list)
1509 {
1510 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1511 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1512 last_active_in = usecase->stream.in;
1513 }
1514 }
1515
1516 return last_active_in;
1517}
1518
1519struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1520{
1521 struct listnode *node;
1522
1523 /* First check active inputs with voice communication source and then
1524 * any input if audio mode is in communication */
1525 list_for_each(node, &adev->usecase_list)
1526 {
1527 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1528 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1529 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1530 return usecase->stream.in;
1531 }
1532 }
1533 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1534 return adev_get_active_input(adev);
1535 }
1536 return NULL;
1537}
1538
Carter Hsub0c91482019-05-14 18:50:52 +08001539/*
1540 * Aligned with policy.h
1541 */
1542static inline int source_priority(int inputSource)
1543{
1544 switch (inputSource) {
1545 case AUDIO_SOURCE_VOICE_COMMUNICATION:
1546 return 9;
1547 case AUDIO_SOURCE_CAMCORDER:
1548 return 8;
1549 case AUDIO_SOURCE_VOICE_PERFORMANCE:
1550 return 7;
1551 case AUDIO_SOURCE_UNPROCESSED:
1552 return 6;
1553 case AUDIO_SOURCE_MIC:
1554 return 5;
1555 case AUDIO_SOURCE_ECHO_REFERENCE:
1556 return 4;
1557 case AUDIO_SOURCE_FM_TUNER:
1558 return 3;
1559 case AUDIO_SOURCE_VOICE_RECOGNITION:
1560 return 2;
1561 case AUDIO_SOURCE_HOTWORD:
1562 return 1;
1563 default:
1564 break;
1565 }
1566 return 0;
1567}
1568
1569static struct stream_in *get_priority_input(struct audio_device *adev)
1570{
1571 struct listnode *node;
1572 struct audio_usecase *usecase;
1573 int last_priority = 0, priority;
1574 struct stream_in *priority_in = NULL;
1575 struct stream_in *in;
1576
1577 list_for_each(node, &adev->usecase_list) {
1578 usecase = node_to_item(node, struct audio_usecase, list);
1579 if (usecase->type == PCM_CAPTURE) {
1580 in = usecase->stream.in;
1581 if (!in)
1582 continue;
1583 priority = source_priority(in->source);
1584
1585 if (priority > last_priority) {
1586 last_priority = priority;
1587 priority_in = in;
1588 }
1589 }
1590 }
1591 return priority_in;
1592}
1593
HW Leef88584d2019-03-18 17:27:18 +08001594int select_devices_with_force_switch(struct audio_device *adev,
1595 audio_usecase_t uc_id,
1596 bool force_switch)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001598 snd_device_t out_snd_device = SND_DEVICE_NONE;
1599 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600 struct audio_usecase *usecase = NULL;
1601 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001602 struct audio_usecase *hfp_usecase = NULL;
1603 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001604 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001606 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1607 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001609 usecase = get_usecase_from_list(adev, uc_id);
1610 if (usecase == NULL) {
1611 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1612 return -EINVAL;
1613 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001615 if ((usecase->type == VOICE_CALL) ||
1616 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001617 out_snd_device = platform_get_output_snd_device(adev->platform,
1618 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001619 in_snd_device = platform_get_input_snd_device(adev->platform,
1620 NULL,
1621 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001622 usecase->devices = usecase->stream.out->devices;
1623 } else {
1624 /*
1625 * If the voice call is active, use the sound devices of voice call usecase
1626 * so that it would not result any device switch. All the usecases will
1627 * be switched to new device when select_devices() is called for voice call
1628 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001629 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001630 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001631 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001632 vc_usecase = get_usecase_from_list(adev,
1633 get_voice_usecase_id_from_list(adev));
1634 if ((vc_usecase != NULL) &&
1635 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001636 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1637 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001638 in_snd_device = vc_usecase->in_snd_device;
1639 out_snd_device = vc_usecase->out_snd_device;
1640 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001641 } else if (audio_extn_hfp_is_active(adev)) {
1642 hfp_ucid = audio_extn_hfp_get_usecase();
1643 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1644 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1645 in_snd_device = hfp_usecase->in_snd_device;
1646 out_snd_device = hfp_usecase->out_snd_device;
1647 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001648 }
1649 if (usecase->type == PCM_PLAYBACK) {
1650 usecase->devices = usecase->stream.out->devices;
1651 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001652 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001653 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001654 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001655
Eric Laurentb23d5282013-05-14 15:27:20 -07001656 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001657 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001658
1659 if (voip_usecase)
1660 voip_out = voip_usecase->stream.out;
1661
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001662 if (usecase->stream.out == voip_out && voip_in != NULL) {
1663 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001664 }
1665 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001666 } else if (usecase->type == PCM_CAPTURE) {
1667 usecase->devices = usecase->stream.in->device;
1668 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001669 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001670 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001671 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsub0c91482019-05-14 18:50:52 +08001672 struct stream_in *priority_in = NULL;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001673
1674 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001675 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1676 USECASE_AUDIO_PLAYBACK_VOIP);
1677
Carter Hsub0c91482019-05-14 18:50:52 +08001678 usecase->stream.in->enable_ec_port = false;
1679
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001680 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1681 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001682 } else if (voip_usecase) {
1683 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001684 } else if (adev->primary_output &&
1685 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001686 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001687 } else {
1688 /* forcing speaker o/p device to get matching i/p pair
1689 in case o/p is not routed from same primary HAL */
1690 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001691 }
Carter Hsub0c91482019-05-14 18:50:52 +08001692 priority_in = voip_in;
1693 } else {
1694 /* get the input with the highest priority source*/
1695 priority_in = get_priority_input(adev);
1696
1697 if (!priority_in)
1698 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001699 }
Carter Hsub0c91482019-05-14 18:50:52 +08001700
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001701 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsub0c91482019-05-14 18:50:52 +08001702 priority_in,
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001703 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001704 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001705 }
1706 }
1707
1708 if (out_snd_device == usecase->out_snd_device &&
1709 in_snd_device == usecase->in_snd_device) {
HW Leef88584d2019-03-18 17:27:18 +08001710 if (!force_device_switch(usecase) && !force_switch)
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001711 return 0;
1712 }
1713
1714 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1715 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1716 return 0;
1717 }
1718
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001719 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1720 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001721 (!audio_extn_a2dp_is_ready())) {
1722 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001723 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1724 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1725 else
1726 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 }
1728
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07001729 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK ||
1730 usecase->id == USECASE_INCALL_MUSIC_UPLINK2) {
juyuchen66c4ecf2018-08-06 15:39:34 +08001731 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1732 }
1733
Eric Laurent2bafff12016-03-17 12:17:23 -07001734 if (out_snd_device != SND_DEVICE_NONE &&
1735 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1736 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1737 __func__,
1738 use_case_table[uc_id],
1739 adev->last_logged_snd_device[uc_id][0],
1740 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1741 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1742 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1743 -1,
1744 out_snd_device,
1745 platform_get_snd_device_name(out_snd_device),
1746 platform_get_snd_device_acdb_id(out_snd_device));
1747 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1748 }
1749 if (in_snd_device != SND_DEVICE_NONE &&
1750 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1751 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1752 __func__,
1753 use_case_table[uc_id],
1754 adev->last_logged_snd_device[uc_id][1],
1755 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1756 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1757 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1758 -1,
1759 in_snd_device,
1760 platform_get_snd_device_name(in_snd_device),
1761 platform_get_snd_device_acdb_id(in_snd_device));
1762 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1763 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 /*
1766 * Limitation: While in call, to do a device switch we need to disable
1767 * and enable both RX and TX devices though one of them is same as current
1768 * device.
1769 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001770 if ((usecase->type == VOICE_CALL) &&
1771 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1772 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001773 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001774 /* Disable sidetone only if voice call already exists */
1775 if (voice_is_call_state_active(adev))
1776 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001777 }
1778
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001779 /* Disable current sound devices */
1780 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001781 disable_audio_route(adev, usecase);
1782 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 }
1784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001786 disable_audio_route(adev, usecase);
1787 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
1789
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001790 /* Applicable only on the targets that has external modem.
1791 * New device information should be sent to modem before enabling
1792 * the devices to reduce in-call device switch time.
1793 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001794 if ((usecase->type == VOICE_CALL) &&
1795 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1796 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001797 status = platform_switch_voice_call_enable_device_config(adev->platform,
1798 out_snd_device,
1799 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001800 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001801
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 /* Enable new sound devices */
1803 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001804 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001805 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1806 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001807 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001808 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809 }
1810
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001811 if (in_snd_device != SND_DEVICE_NONE) {
1812 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001813 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001814 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001815
Eric Laurentb23d5282013-05-14 15:27:20 -07001816 if (usecase->type == VOICE_CALL)
1817 status = platform_switch_voice_call_device_post(adev->platform,
1818 out_snd_device,
1819 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001820
sangwoo170731f2013-06-08 15:36:36 +09001821 usecase->in_snd_device = in_snd_device;
1822 usecase->out_snd_device = out_snd_device;
1823
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001824 audio_extn_tfa_98xx_set_mode();
1825
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001826 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001827
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001828 /* If input stream is already running the effect needs to be
1829 applied on the new input device that's being enabled here. */
1830 if (in_snd_device != SND_DEVICE_NONE)
1831 check_and_enable_effect(adev);
1832
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001833 /* Applicable only on the targets that has external modem.
1834 * Enable device command should be sent to modem only after
1835 * enabling voice call mixer controls
1836 */
vivek mehta765eb642015-08-07 19:46:06 -07001837 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001838 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1839 out_snd_device,
1840 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001841 /* Enable sidetone only if voice call already exists */
1842 if (voice_is_call_state_active(adev))
1843 voice_set_sidetone(adev, out_snd_device, true);
1844 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001845
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001846 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001847 struct stream_out *voip_out = voip_usecase->stream.out;
1848 audio_extn_utils_send_app_type_gain(adev,
1849 voip_out->app_type_cfg.app_type,
1850 &voip_out->app_type_cfg.gain[0]);
1851 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 return status;
1853}
1854
HW Leef88584d2019-03-18 17:27:18 +08001855int select_devices(struct audio_device *adev,
1856 audio_usecase_t uc_id)
1857{
1858 return select_devices_with_force_switch(adev, uc_id, false);
1859}
1860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861static int stop_input_stream(struct stream_in *in)
1862{
1863 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 struct audio_usecase *uc_info;
1865 struct audio_device *adev = in->dev;
Carter Hsub0c91482019-05-14 18:50:52 +08001866 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867
Eric Laurent994a6932013-07-17 11:51:42 -07001868 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001871 uc_info = get_usecase_from_list(adev, in->usecase);
1872 if (uc_info == NULL) {
1873 ALOGE("%s: Could not find the usecase (%d) in the list",
1874 __func__, in->usecase);
1875 return -EINVAL;
1876 }
1877
Carter Hsub0c91482019-05-14 18:50:52 +08001878 priority_in = get_priority_input(adev);
1879
vivek mehta781065c2017-04-04 12:55:01 -07001880 /* Close in-call recording streams */
1881 voice_check_and_stop_incall_rec_usecase(adev, in);
1882
Eric Laurent150dbfe2013-02-27 14:31:02 -08001883 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001884 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001885
1886 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001887 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001889 list_remove(&uc_info->list);
1890 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891
Carter Hsub0c91482019-05-14 18:50:52 +08001892 if (priority_in == in) {
1893 priority_in = get_priority_input(adev);
1894 if (priority_in)
1895 select_devices(adev, priority_in->usecase);
1896 }
1897
Eric Laurent994a6932013-07-17 11:51:42 -07001898 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899 return ret;
1900}
1901
1902int start_input_stream(struct stream_in *in)
1903{
1904 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001905 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 struct audio_usecase *uc_info;
1907 struct audio_device *adev = in->dev;
1908
Eric Laurent994a6932013-07-17 11:51:42 -07001909 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001910
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001911 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1912 return -EIO;
1913
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001914 if (in->card_status == CARD_STATUS_OFFLINE ||
1915 adev->card_status == CARD_STATUS_OFFLINE) {
1916 ALOGW("in->card_status or adev->card_status offline, try again");
1917 ret = -EAGAIN;
1918 goto error_config;
1919 }
1920
vivek mehta781065c2017-04-04 12:55:01 -07001921 /* Check if source matches incall recording usecase criteria */
1922 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1923 if (ret)
1924 goto error_config;
1925 else
1926 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1927
Eric Laurentb23d5282013-05-14 15:27:20 -07001928 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 if (in->pcm_device_id < 0) {
1930 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1931 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001932 ret = -EINVAL;
1933 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1937 uc_info->id = in->usecase;
1938 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001939 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001940 uc_info->devices = in->device;
1941 uc_info->in_snd_device = SND_DEVICE_NONE;
1942 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001944 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001945
Wei Wangf4837d52017-11-21 14:51:20 -08001946 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001947 audio_extn_perf_lock_acquire();
1948
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950
Eric Laurent0e46adf2016-12-16 12:49:24 -08001951 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001952 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001953 ALOGE("%s: pcm stream not ready", __func__);
1954 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001955 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001956 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001957 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001958 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1959 goto error_open;
1960 }
1961 } else {
1962 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1963 unsigned int pcm_open_retry_count = 0;
1964
1965 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1966 flags |= PCM_MMAP | PCM_NOIRQ;
1967 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1968 } else if (in->realtime) {
1969 flags |= PCM_MMAP | PCM_NOIRQ;
1970 }
1971
1972 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1973 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1974
1975 while (1) {
1976 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1977 flags, &in->config);
1978 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1979 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1980 if (in->pcm != NULL) {
1981 pcm_close(in->pcm);
1982 in->pcm = NULL;
1983 }
1984 if (pcm_open_retry_count-- == 0) {
1985 ret = -EIO;
1986 goto error_open;
1987 }
1988 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1989 continue;
1990 }
1991 break;
1992 }
1993
1994 ALOGV("%s: pcm_prepare", __func__);
1995 ret = pcm_prepare(in->pcm);
1996 if (ret < 0) {
1997 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001998 pcm_close(in->pcm);
1999 in->pcm = NULL;
2000 goto error_open;
2001 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002002 if (in->realtime) {
2003 ret = pcm_start(in->pcm);
2004 if (ret < 0) {
2005 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2006 pcm_close(in->pcm);
2007 in->pcm = NULL;
2008 goto error_open;
2009 }
2010 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002011 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002012 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08002013 check_and_enable_effect(adev);
justinwengc6347db2019-02-21 18:49:00 +08002014 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2015 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Wei Wangf4837d52017-11-21 14:51:20 -08002016 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002017 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07002018 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002019
Eric Laurent0e46adf2016-12-16 12:49:24 -08002020 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08002021
2022error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002023 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08002024 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002025 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08002026
2027error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07002028 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002029 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030}
2031
Eric Laurenta1478072015-09-21 17:21:52 -07002032void lock_input_stream(struct stream_in *in)
2033{
2034 pthread_mutex_lock(&in->pre_lock);
2035 pthread_mutex_lock(&in->lock);
2036 pthread_mutex_unlock(&in->pre_lock);
2037}
2038
2039void lock_output_stream(struct stream_out *out)
2040{
2041 pthread_mutex_lock(&out->pre_lock);
2042 pthread_mutex_lock(&out->lock);
2043 pthread_mutex_unlock(&out->pre_lock);
2044}
2045
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002046/* must be called with out->lock locked */
2047static int send_offload_cmd_l(struct stream_out* out, int command)
2048{
2049 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2050
2051 ALOGVV("%s %d", __func__, command);
2052
2053 cmd->cmd = command;
2054 list_add_tail(&out->offload_cmd_list, &cmd->node);
2055 pthread_cond_signal(&out->offload_cond);
2056 return 0;
2057}
2058
2059/* must be called iwth out->lock locked */
2060static void stop_compressed_output_l(struct stream_out *out)
2061{
2062 out->offload_state = OFFLOAD_STATE_IDLE;
2063 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002064 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 if (out->compr != NULL) {
2066 compress_stop(out->compr);
2067 while (out->offload_thread_blocked) {
2068 pthread_cond_wait(&out->cond, &out->lock);
2069 }
2070 }
2071}
2072
2073static void *offload_thread_loop(void *context)
2074{
2075 struct stream_out *out = (struct stream_out *) context;
2076 struct listnode *item;
2077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2079 set_sched_policy(0, SP_FOREGROUND);
2080 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2081
2082 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08002083
Eric Laurenta1478072015-09-21 17:21:52 -07002084 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08002085 out->offload_state = OFFLOAD_STATE_IDLE;
2086 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 for (;;) {
2088 struct offload_cmd *cmd = NULL;
2089 stream_callback_event_t event;
2090 bool send_callback = false;
2091
2092 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2093 __func__, list_empty(&out->offload_cmd_list),
2094 out->offload_state);
2095 if (list_empty(&out->offload_cmd_list)) {
2096 ALOGV("%s SLEEPING", __func__);
2097 pthread_cond_wait(&out->offload_cond, &out->lock);
2098 ALOGV("%s RUNNING", __func__);
2099 continue;
2100 }
2101
2102 item = list_head(&out->offload_cmd_list);
2103 cmd = node_to_item(item, struct offload_cmd, node);
2104 list_remove(item);
2105
2106 ALOGVV("%s STATE %d CMD %d out->compr %p",
2107 __func__, out->offload_state, cmd->cmd, out->compr);
2108
2109 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2110 free(cmd);
2111 break;
2112 }
2113
2114 if (out->compr == NULL) {
2115 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07002116 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 pthread_cond_signal(&out->cond);
2118 continue;
2119 }
2120 out->offload_thread_blocked = true;
2121 pthread_mutex_unlock(&out->lock);
2122 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002123 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2125 compress_wait(out->compr, -1);
2126 send_callback = true;
2127 event = STREAM_CBK_EVENT_WRITE_READY;
2128 break;
2129 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002130 compress_next_track(out->compr);
2131 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002132 send_callback = true;
2133 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002134 /* Resend the metadata for next iteration */
2135 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 break;
2137 case OFFLOAD_CMD_DRAIN:
2138 compress_drain(out->compr);
2139 send_callback = true;
2140 event = STREAM_CBK_EVENT_DRAIN_READY;
2141 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002142 case OFFLOAD_CMD_ERROR:
2143 send_callback = true;
2144 event = STREAM_CBK_EVENT_ERROR;
2145 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002146 default:
2147 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2148 break;
2149 }
Eric Laurenta1478072015-09-21 17:21:52 -07002150 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 out->offload_thread_blocked = false;
2152 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002153 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002154 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002156 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002157 free(cmd);
2158 }
2159
2160 pthread_cond_signal(&out->cond);
2161 while (!list_empty(&out->offload_cmd_list)) {
2162 item = list_head(&out->offload_cmd_list);
2163 list_remove(item);
2164 free(node_to_item(item, struct offload_cmd, node));
2165 }
2166 pthread_mutex_unlock(&out->lock);
2167
2168 return NULL;
2169}
2170
2171static int create_offload_callback_thread(struct stream_out *out)
2172{
2173 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2174 list_init(&out->offload_cmd_list);
2175 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2176 offload_thread_loop, out);
2177 return 0;
2178}
2179
2180static int destroy_offload_callback_thread(struct stream_out *out)
2181{
Eric Laurenta1478072015-09-21 17:21:52 -07002182 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 stop_compressed_output_l(out);
2184 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2185
2186 pthread_mutex_unlock(&out->lock);
2187 pthread_join(out->offload_thread, (void **) NULL);
2188 pthread_cond_destroy(&out->offload_cond);
2189
2190 return 0;
2191}
2192
Eric Laurent07eeafd2013-10-06 12:52:49 -07002193static bool allow_hdmi_channel_config(struct audio_device *adev)
2194{
2195 struct listnode *node;
2196 struct audio_usecase *usecase;
2197 bool ret = true;
2198
2199 list_for_each(node, &adev->usecase_list) {
2200 usecase = node_to_item(node, struct audio_usecase, list);
2201 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2202 /*
2203 * If voice call is already existing, do not proceed further to avoid
2204 * disabling/enabling both RX and TX devices, CSD calls, etc.
2205 * Once the voice call done, the HDMI channels can be configured to
2206 * max channels of remaining use cases.
2207 */
2208 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002209 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002210 __func__);
2211 ret = false;
2212 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002213 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2214 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002215 "no change in HDMI channels", __func__);
2216 ret = false;
2217 break;
2218 }
2219 }
2220 }
2221 return ret;
2222}
2223
2224static int check_and_set_hdmi_channels(struct audio_device *adev,
2225 unsigned int channels)
2226{
2227 struct listnode *node;
2228 struct audio_usecase *usecase;
2229
2230 /* Check if change in HDMI channel config is allowed */
2231 if (!allow_hdmi_channel_config(adev))
2232 return 0;
2233
2234 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002235 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002236 return 0;
2237 }
2238
2239 platform_set_hdmi_channels(adev->platform, channels);
2240 adev->cur_hdmi_channels = channels;
2241
2242 /*
2243 * Deroute all the playback streams routed to HDMI so that
2244 * the back end is deactivated. Note that backend will not
2245 * be deactivated if any one stream is connected to it.
2246 */
2247 list_for_each(node, &adev->usecase_list) {
2248 usecase = node_to_item(node, struct audio_usecase, list);
2249 if (usecase->type == PCM_PLAYBACK &&
2250 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002251 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002252 }
2253 }
2254
2255 /*
2256 * Enable all the streams disabled above. Now the HDMI backend
2257 * will be activated with new channel configuration
2258 */
2259 list_for_each(node, &adev->usecase_list) {
2260 usecase = node_to_item(node, struct audio_usecase, list);
2261 if (usecase->type == PCM_PLAYBACK &&
2262 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002263 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002264 }
2265 }
2266
2267 return 0;
2268}
2269
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002270static int check_and_set_usb_service_interval(struct audio_device *adev,
2271 struct audio_usecase *uc_info,
2272 bool min)
2273{
2274 struct listnode *node;
2275 struct audio_usecase *usecase;
2276 bool switch_usecases = false;
2277 bool reconfig = false;
2278
2279 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2280 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2281 return -1;
2282
2283 /* set if the valid usecase do not already exist */
2284 list_for_each(node, &adev->usecase_list) {
2285 usecase = node_to_item(node, struct audio_usecase, list);
2286 if (usecase->type == PCM_PLAYBACK &&
2287 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2288 switch (usecase->id) {
2289 case USECASE_AUDIO_PLAYBACK_MMAP:
2290 case USECASE_AUDIO_PLAYBACK_ULL:
2291 // cannot reconfig while mmap/ull is present.
2292 return -1;
2293 default:
2294 switch_usecases = true;
2295 break;
2296 }
2297 }
2298 if (switch_usecases)
2299 break;
2300 }
2301 /*
2302 * client can try to set service interval in start_output_stream
2303 * to min or to 0 (i.e reset) in stop_output_stream .
2304 */
2305 unsigned long service_interval =
2306 audio_extn_usb_find_service_interval(min, true /*playback*/);
2307 int ret = platform_set_usb_service_interval(adev->platform,
2308 true /*playback*/,
2309 service_interval,
2310 &reconfig);
2311 /* no change or not supported or no active usecases */
2312 if (ret || !reconfig || !switch_usecases)
2313 return -1;
2314 return 0;
2315#undef VALID_USECASE
2316}
2317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318static int stop_output_stream(struct stream_out *out)
2319{
2320 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 struct audio_usecase *uc_info;
2322 struct audio_device *adev = out->dev;
2323
Eric Laurent994a6932013-07-17 11:51:42 -07002324 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002325 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326 uc_info = get_usecase_from_list(adev, out->usecase);
2327 if (uc_info == NULL) {
2328 ALOGE("%s: Could not find the usecase (%d) in the list",
2329 __func__, out->usecase);
2330 return -EINVAL;
2331 }
2332
Haynes Mathew George41f86652014-06-17 14:22:15 -07002333 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2334 if (adev->visualizer_stop_output != NULL)
2335 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2336 if (adev->offload_effects_stop_output != NULL)
2337 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002338 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2339 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2340 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002341 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002342
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07002343 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2344 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002345 voice_set_device_mute_flag(adev, false);
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07002346 }
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002347
Eric Laurent150dbfe2013-02-27 14:31:02 -08002348 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002349 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002350
2351 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002352 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002354 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355
Eric Laurent0499d4f2014-08-25 22:39:29 -05002356 audio_extn_extspk_update(adev->extspk);
2357
Eric Laurent07eeafd2013-10-06 12:52:49 -07002358 /* Must be called after removing the usecase from list */
2359 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2360 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002361 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002362 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2363 if (ret == 0) {
2364 /* default service interval was successfully updated,
2365 reopen USB backend with new service interval */
2366 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2367 }
2368 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002369 }
juyuchend194b432018-11-16 14:15:16 +08002370 /* 1) media + voip output routing to handset must route media back to
2371 speaker when voip stops.
2372 2) trigger voip input to reroute when voip output changes to
2373 hearing aid. */
Robert Leec5271f72019-04-16 18:46:02 +08002374 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP ||
2375 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
HW Lee88512e92018-06-12 15:26:09 +08002376 struct listnode *node;
2377 struct audio_usecase *usecase;
2378 list_for_each(node, &adev->usecase_list) {
2379 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002380 if ((usecase->type == PCM_CAPTURE &&
2381 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2382 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002383 continue;
2384
2385 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2386 __func__, usecase->id, use_case_table[usecase->id],
2387 out->usecase, use_case_table[out->usecase]);
2388 select_devices(adev, usecase->id);
2389 }
2390 }
2391
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002392 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002393 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 return ret;
2395}
2396
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002397struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2398 unsigned int flags, unsigned int pcm_open_retry_count,
2399 struct pcm_config *config)
2400{
2401 struct pcm* pcm = NULL;
2402
2403 while (1) {
2404 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2405 if (pcm == NULL || !pcm_is_ready(pcm)) {
2406 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2407 if (pcm != NULL) {
2408 pcm_close(pcm);
2409 pcm = NULL;
2410 }
2411 if (pcm_open_retry_count-- == 0)
2412 return NULL;
2413
2414 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2415 continue;
2416 }
2417 break;
2418 }
2419
2420 if (pcm_is_ready(pcm)) {
2421 int ret = pcm_prepare(pcm);
2422 if (ret < 0) {
2423 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2424 pcm_close(pcm);
2425 pcm = NULL;
2426 }
2427 }
2428
2429 return pcm;
2430}
2431
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432int start_output_stream(struct stream_out *out)
2433{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435 struct audio_usecase *uc_info;
2436 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002437 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002438
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002439 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2440 __func__, out->usecase, use_case_table[out->usecase],
2441 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2442 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002443
2444 if (out->card_status == CARD_STATUS_OFFLINE ||
2445 adev->card_status == CARD_STATUS_OFFLINE) {
2446 ALOGW("out->card_status or adev->card_status offline, try again");
2447 ret = -EAGAIN;
2448 goto error_config;
2449 }
2450
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07002451 //Update incall music usecase to reflect correct voice session
2452 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2453 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
2454 if (ret != 0) {
2455 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2456 __func__, ret);
2457 goto error_config;
2458 }
2459 }
2460
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002461 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2462 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002463 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002464 a2dp_combo = true;
2465 } else {
2466 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2467 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2468 ret = -EAGAIN;
2469 goto error_config;
2470 }
2471 }
2472 }
2473 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002474 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 if (out->pcm_device_id < 0) {
2476 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2477 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002478 ret = -EINVAL;
2479 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 }
2481
2482 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2483 uc_info->id = out->usecase;
2484 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002485 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002486 uc_info->devices = out->devices;
2487 uc_info->in_snd_device = SND_DEVICE_NONE;
2488 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489
Eric Laurent07eeafd2013-10-06 12:52:49 -07002490 /* This must be called before adding this usecase to the list */
2491 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2492 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002493 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2494 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2495 /* USB backend is not reopened immediately.
2496 This is eventually done as part of select_devices */
2497 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002498
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002499 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500
Wei Wangf4837d52017-11-21 14:51:20 -08002501 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002502 audio_extn_perf_lock_acquire();
2503
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002504 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2505 (!audio_extn_a2dp_is_ready())) {
2506 if (!a2dp_combo) {
2507 check_a2dp_restore_l(adev, out, false);
2508 } else {
2509 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002510 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2511 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2512 else
2513 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002514 select_devices(adev, out->usecase);
2515 out->devices = dev;
2516 }
2517 } else {
2518 select_devices(adev, out->usecase);
2519 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002520
Eric Laurent0499d4f2014-08-25 22:39:29 -05002521 audio_extn_extspk_update(adev->extspk);
2522
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07002523 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
2524 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002525 voice_set_device_mute_flag(adev, true);
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07002526 }
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002527
Andy Hung31aca912014-03-20 17:14:59 -07002528 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002529 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002530 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2531 out->pcm = NULL;
2532 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2533 COMPRESS_IN, &out->compr_config);
2534 if (out->compr && !is_compress_ready(out->compr)) {
2535 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2536 compress_close(out->compr);
2537 out->compr = NULL;
2538 ret = -EIO;
2539 goto error_open;
2540 }
2541 if (out->offload_callback)
2542 compress_nonblock(out->compr, out->non_blocking);
2543
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002544 if (adev->visualizer_start_output != NULL) {
2545 int capture_device_id =
2546 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2547 PCM_CAPTURE);
2548 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2549 adev->snd_card, capture_device_id);
2550 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002551 if (adev->offload_effects_start_output != NULL)
2552 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2553 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002554 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002555 ALOGE("%s: pcm stream not ready", __func__);
2556 goto error_open;
2557 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002558 ret = pcm_start(out->pcm);
2559 if (ret < 0) {
2560 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2561 goto error_open;
2562 }
2563 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002564 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002565 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002566
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002567 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2568 flags |= PCM_MMAP | PCM_NOIRQ;
2569 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002570 } else if (out->realtime) {
2571 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002572 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002573
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002574 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2575 flags, pcm_open_retry_count,
2576 &(out->config));
2577 if (out->pcm == NULL) {
2578 ret = -EIO;
2579 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002581
2582 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2583 if (adev->haptic_pcm != NULL) {
2584 pcm_close(adev->haptic_pcm);
2585 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002586 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002587 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2588 adev->haptic_pcm_device_id,
2589 flags, pcm_open_retry_count,
2590 &(adev->haptics_config));
2591 // failure to open haptics pcm shouldnt stop audio,
2592 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002593 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002594
Eric Laurent0e46adf2016-12-16 12:49:24 -08002595 if (out->realtime) {
2596 ret = pcm_start(out->pcm);
2597 if (ret < 0) {
2598 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2599 pcm_close(out->pcm);
2600 out->pcm = NULL;
2601 goto error_open;
2602 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002603 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002604 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002605
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002606 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002607 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002608 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002609 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002610
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002611 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2612 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2613 audio_low_latency_hint_start();
2614 }
2615
vivek mehtae59cfb22017-06-16 15:57:11 -07002616 // consider a scenario where on pause lower layers are tear down.
2617 // so on resume, swap mixer control need to be sent only when
2618 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002619 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002620
2621 platform_set_swap_channels(adev, true);
2622
Eric Laurent994a6932013-07-17 11:51:42 -07002623 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002624 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002626 if (adev->haptic_pcm) {
2627 pcm_close(adev->haptic_pcm);
2628 adev->haptic_pcm = NULL;
2629 }
Wei Wangf4837d52017-11-21 14:51:20 -08002630 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002631 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002633error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002634 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635}
2636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637static int check_input_parameters(uint32_t sample_rate,
2638 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002639 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002641 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2642 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002643 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2644 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002645 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2646 return -EINVAL;
2647 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648
Eric Laurent74b55762017-07-09 17:04:53 -07002649 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2650 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002651 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002652 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002653 return -EINVAL;
2654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655
2656 switch (sample_rate) {
2657 case 8000:
2658 case 11025:
2659 case 12000:
2660 case 16000:
2661 case 22050:
2662 case 24000:
2663 case 32000:
2664 case 44100:
2665 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002666 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 break;
2668 default:
vivek mehtadae44712015-07-27 14:13:18 -07002669 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 return -EINVAL;
2671 }
2672
2673 return 0;
2674}
2675
Kevin Rocarda325aa22018-04-03 09:15:52 -07002676/** Add a value in a list if not already present.
2677 * @return true if value was successfully inserted or already present,
2678 * false if the list is full and does not contain the value.
2679 */
2680static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2681 for (size_t i = 0; i < list_length; i++) {
2682 if (list[i] == value) return true; // value is already present
2683 if (list[i] == 0) { // no values in this slot
2684 list[i] = value;
2685 return true; // value inserted
2686 }
2687 }
2688 return false; // could not insert value
2689}
2690
2691/** Add channel_mask in supported_channel_masks if not already present.
2692 * @return true if channel_mask was successfully inserted or already present,
2693 * false if supported_channel_masks is full and does not contain channel_mask.
2694 */
2695static void register_channel_mask(audio_channel_mask_t channel_mask,
2696 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2697 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2698 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2699}
2700
2701/** Add format in supported_formats if not already present.
2702 * @return true if format was successfully inserted or already present,
2703 * false if supported_formats is full and does not contain format.
2704 */
2705static void register_format(audio_format_t format,
2706 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2707 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2708 "%s: stream can not declare supporting its format %x", __func__, format);
2709}
2710/** Add sample_rate in supported_sample_rates if not already present.
2711 * @return true if sample_rate was successfully inserted or already present,
2712 * false if supported_sample_rates is full and does not contain sample_rate.
2713 */
2714static void register_sample_rate(uint32_t sample_rate,
2715 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2716 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2717 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2718}
2719
vivek mehtaa68fea62017-06-08 19:04:02 -07002720static size_t get_stream_buffer_size(size_t duration_ms,
2721 uint32_t sample_rate,
2722 audio_format_t format,
2723 int channel_count,
2724 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725{
2726 size_t size = 0;
2727
vivek mehtaa68fea62017-06-08 19:04:02 -07002728 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002729 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002730 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002731
2732 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733
Glenn Kasten4f993392014-05-14 07:30:48 -07002734 /* make sure the size is multiple of 32 bytes
2735 * At 48 kHz mono 16-bit PCM:
2736 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2737 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2738 */
2739 size += 0x1f;
2740 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002741
2742 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002743}
2744
2745static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2746{
2747 struct stream_out *out = (struct stream_out *)stream;
2748
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750}
2751
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002752static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002753{
2754 return -ENOSYS;
2755}
2756
2757static size_t out_get_buffer_size(const struct audio_stream *stream)
2758{
2759 struct stream_out *out = (struct stream_out *)stream;
2760
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2762 return out->compr_config.fragment_size;
2763 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002764 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002765 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766}
2767
2768static uint32_t out_get_channels(const struct audio_stream *stream)
2769{
2770 struct stream_out *out = (struct stream_out *)stream;
2771
2772 return out->channel_mask;
2773}
2774
2775static audio_format_t out_get_format(const struct audio_stream *stream)
2776{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777 struct stream_out *out = (struct stream_out *)stream;
2778
2779 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780}
2781
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002782static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783{
2784 return -ENOSYS;
2785}
2786
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002787/* must be called with out->lock locked */
2788static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002789{
2790 struct stream_out *out = (struct stream_out *)stream;
2791 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002792 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002795 if (adev->adm_deregister_stream)
2796 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002797 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002798 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2800 if (out->pcm) {
2801 pcm_close(out->pcm);
2802 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002803
2804 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2805 if (adev->haptic_pcm) {
2806 pcm_close(adev->haptic_pcm);
2807 adev->haptic_pcm = NULL;
2808 }
2809
2810 if (adev->haptic_buffer != NULL) {
2811 free(adev->haptic_buffer);
2812 adev->haptic_buffer = NULL;
2813 adev->haptic_buffer_size = 0;
2814 }
2815 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002817 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002818 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002819 out->playback_started = false;
2820 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 } else {
2822 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002823 out->gapless_mdata.encoder_delay = 0;
2824 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002825 if (out->compr != NULL) {
2826 compress_close(out->compr);
2827 out->compr = NULL;
2828 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002829 }
Phil Burkbc991042017-02-24 08:06:44 -08002830 if (do_stop) {
2831 stop_output_stream(out);
2832 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002833 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002835 return 0;
2836}
2837
2838static int out_standby(struct audio_stream *stream)
2839{
2840 struct stream_out *out = (struct stream_out *)stream;
2841
2842 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2843 out->usecase, use_case_table[out->usecase]);
2844
2845 lock_output_stream(out);
2846 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 return 0;
2850}
2851
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002852static int out_on_error(struct audio_stream *stream)
2853{
2854 struct stream_out *out = (struct stream_out *)stream;
2855 struct audio_device *adev = out->dev;
2856 bool do_standby = false;
2857
2858 lock_output_stream(out);
2859 if (!out->standby) {
2860 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2861 stop_compressed_output_l(out);
2862 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2863 } else
2864 do_standby = true;
2865 }
2866 pthread_mutex_unlock(&out->lock);
2867
2868 if (do_standby)
2869 return out_standby(&out->stream.common);
2870
2871 return 0;
2872}
2873
Andy Hung7401c7c2016-09-21 12:41:21 -07002874static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875{
Andy Hung7401c7c2016-09-21 12:41:21 -07002876 struct stream_out *out = (struct stream_out *)stream;
2877
2878 // We try to get the lock for consistency,
2879 // but it isn't necessary for these variables.
2880 // If we're not in standby, we may be blocked on a write.
2881 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2882 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2883 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2884
Andy Hung572633e2019-02-19 11:58:24 -08002885 char buffer[256]; // for statistics formatting
2886 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2887 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2888
Andy Hung241e36f2019-02-19 12:00:38 -08002889 if (out->start_latency_ms.n > 0) {
2890 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2891 dprintf(fd, " Start latency ms: %s\n", buffer);
2892 }
2893
Andy Hung7401c7c2016-09-21 12:41:21 -07002894 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002895 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002896 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002897
2898 // dump error info
2899 (void)error_log_dump(
2900 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002902 return 0;
2903}
2904
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002905static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2906{
2907 int ret = 0;
2908 char value[32];
2909 struct compr_gapless_mdata tmp_mdata;
2910
2911 if (!out || !parms) {
2912 return -EINVAL;
2913 }
2914
2915 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2916 if (ret >= 0) {
2917 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2918 } else {
2919 return -EINVAL;
2920 }
2921
2922 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2923 if (ret >= 0) {
2924 tmp_mdata.encoder_padding = atoi(value);
2925 } else {
2926 return -EINVAL;
2927 }
2928
2929 out->gapless_mdata = tmp_mdata;
2930 out->send_new_metadata = 1;
2931 ALOGV("%s new encoder delay %u and padding %u", __func__,
2932 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2933
2934 return 0;
2935}
2936
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002937static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2938{
2939 return out == adev->primary_output || out == adev->voice_tx_output;
2940}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002941
Kevin Rocard1e02c882017-08-09 15:26:07 -07002942static int get_alive_usb_card(struct str_parms* parms) {
2943 int card;
2944 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2945 !audio_extn_usb_alive(card)) {
2946 return card;
2947 }
2948 return -ENODEV;
2949}
2950
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2952{
2953 struct stream_out *out = (struct stream_out *)stream;
2954 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002955 struct audio_usecase *usecase;
2956 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002957 struct str_parms *parms;
2958 char value[32];
2959 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002960 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002961 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002962 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963
Eric Laurent2e140aa2016-06-30 17:14:46 -07002964 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002965 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966 parms = str_parms_create_str(kvpairs);
2967 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2968 if (ret >= 0) {
2969 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002970
Eric Laurenta1478072015-09-21 17:21:52 -07002971 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002972
2973 // The usb driver needs to be closed after usb device disconnection
2974 // otherwise audio is no longer played on the new usb devices.
2975 // By forcing the stream in standby, the usb stack refcount drops to 0
2976 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002977 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002978 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002979 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2980 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2981 out_standby_l(&out->stream.common);
2982 }
2983 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002984 }
2985
Eric Laurent150dbfe2013-02-27 14:31:02 -08002986 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002988 /*
2989 * When HDMI cable is unplugged the music playback is paused and
2990 * the policy manager sends routing=0. But the audioflinger
2991 * continues to write data until standby time (3sec).
2992 * As the HDMI core is turned off, the write gets blocked.
2993 * Avoid this by routing audio to speaker until standby.
2994 */
2995 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2996 val == AUDIO_DEVICE_NONE) {
2997 val = AUDIO_DEVICE_OUT_SPEAKER;
2998 }
2999
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003000 /*
3001 * When A2DP is disconnected the
3002 * music playback is paused and the policy manager sends routing=0
3003 * But the audioflingercontinues to write data until standby time
3004 * (3sec). As BT is turned off, the write gets blocked.
3005 * Avoid this by routing audio to speaker until standby.
3006 */
3007 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
3008 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07003009 !audio_extn_a2dp_is_ready() &&
3010 !adev->bt_sco_on) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003011 val = AUDIO_DEVICE_OUT_SPEAKER;
3012 }
3013
3014 /* To avoid a2dp to sco overlapping / BT device improper state
3015 * check with BT lib about a2dp streaming support before routing
3016 */
3017 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3018 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08003019 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003020 //combo usecase just by pass a2dp
3021 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
3022 bypass_a2dp = true;
3023 } else {
3024 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3025 /* update device to a2dp and don't route as BT returned error
3026 * However it is still possible a2dp routing called because
3027 * of current active device disconnection (like wired headset)
3028 */
3029 out->devices = val;
3030 pthread_mutex_unlock(&out->lock);
3031 pthread_mutex_unlock(&adev->lock);
3032 status = -ENOSYS;
3033 goto routing_fail;
3034 }
3035 }
3036 }
3037
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003038 audio_devices_t new_dev = val;
3039
3040 // Workaround: If routing to an non existing usb device, fail gracefully
3041 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003042 int card;
3043 if (audio_is_usb_out_device(new_dev) &&
3044 (card = get_alive_usb_card(parms)) >= 0) {
3045
3046 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003047 pthread_mutex_unlock(&adev->lock);
3048 pthread_mutex_unlock(&out->lock);
3049 status = -ENOSYS;
3050 goto routing_fail;
3051 }
3052
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003053 /*
3054 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07003055 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003056 * the select_devices(). But how do we undo this?
3057 *
3058 * For example, music playback is active on headset (deep-buffer usecase)
3059 * and if we go to ringtones and select a ringtone, low-latency usecase
3060 * will be started on headset+speaker. As we can't enable headset+speaker
3061 * and headset devices at the same time, select_devices() switches the music
3062 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3063 * So when the ringtone playback is completed, how do we undo the same?
3064 *
3065 * We are relying on the out_set_parameters() call on deep-buffer output,
3066 * once the ringtone playback is ended.
3067 * NOTE: We should not check if the current devices are same as new devices.
3068 * Because select_devices() must be called to switch back the music
3069 * playback to headset.
3070 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003071 if (new_dev != AUDIO_DEVICE_NONE) {
3072 bool same_dev = out->devices == new_dev;
3073 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003074
Eric Laurenta7657192014-10-09 21:09:33 -07003075 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08003076 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07003077 if (adev->mode == AUDIO_MODE_IN_CALL) {
3078 adev->current_call_output = out;
3079 ret = voice_start_call(adev);
3080 }
3081 } else {
3082 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003083 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07003084 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003085 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003086
3087 if (!out->standby) {
3088 if (!same_dev) {
3089 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003090 // inform adm before actual routing to prevent glitches.
3091 if (adev->adm_on_routing_change) {
3092 adev->adm_on_routing_change(adev->adm_data,
3093 out->handle);
3094 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003095 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003096 if (!bypass_a2dp) {
3097 select_devices(adev, out->usecase);
3098 } else {
juyuchen9baad392018-06-05 19:02:10 +08003099 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3100 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3101 else
3102 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003103 select_devices(adev, out->usecase);
3104 out->devices = new_dev;
3105 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003106 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07003107
3108 // on device switch force swap, lower functions will make sure
3109 // to check if swap is allowed or not.
3110
3111 if (!same_dev)
3112 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003113
3114 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3115 out->a2dp_compress_mute &&
3116 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
3117 pthread_mutex_lock(&out->compr_mute_lock);
3118 out->a2dp_compress_mute = false;
3119 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3120 pthread_mutex_unlock(&out->compr_mute_lock);
3121 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003122 }
3123
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003124 }
3125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003127 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003128
3129 /*handles device and call state changes*/
3130 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003132 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003133
3134 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3135 parse_compress_metadata(out, parms);
3136 }
3137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003139 ALOGV("%s: exit: code(%d)", __func__, status);
3140 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141}
3142
Haynes Mathew George569b7482017-05-08 14:44:27 -07003143static bool stream_get_parameter_channels(struct str_parms *query,
3144 struct str_parms *reply,
3145 audio_channel_mask_t *supported_channel_masks) {
3146 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003147 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003149 size_t i, j;
3150
3151 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3152 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153 value[0] = '\0';
3154 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003155 while (supported_channel_masks[i] != 0) {
3156 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3157 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 if (!first) {
3159 strcat(value, "|");
3160 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003161 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162 first = false;
3163 break;
3164 }
3165 }
3166 i++;
3167 }
3168 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003169 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003170 return ret >= 0;
3171}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003172
Haynes Mathew George569b7482017-05-08 14:44:27 -07003173static bool stream_get_parameter_formats(struct str_parms *query,
3174 struct str_parms *reply,
3175 audio_format_t *supported_formats) {
3176 int ret = -1;
3177 char value[256];
3178 int i;
3179
3180 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3181 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003182 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003183 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003184 case AUDIO_FORMAT_PCM_16_BIT:
3185 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3186 break;
3187 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3188 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3189 break;
3190 case AUDIO_FORMAT_PCM_32_BIT:
3191 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3192 break;
3193 default:
3194 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003195 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003196 break;
3197 }
3198 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003199 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003200 return ret >= 0;
3201}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003202
Haynes Mathew George569b7482017-05-08 14:44:27 -07003203static bool stream_get_parameter_rates(struct str_parms *query,
3204 struct str_parms *reply,
3205 uint32_t *supported_sample_rates) {
3206
3207 int i;
3208 char value[256];
3209 int ret = -1;
3210 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3211 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003212 value[0] = '\0';
3213 i=0;
3214 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003215 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003216 int avail = sizeof(value) - cursor;
3217 ret = snprintf(value + cursor, avail, "%s%d",
3218 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003219 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003220 if (ret < 0 || ret >= avail) {
3221 // if cursor is at the last element of the array
3222 // overwrite with \0 is duplicate work as
3223 // snprintf already put a \0 in place.
3224 // else
3225 // we had space to write the '|' at value[cursor]
3226 // (which will be overwritten) or no space to fill
3227 // the first element (=> cursor == 0)
3228 value[cursor] = '\0';
3229 break;
3230 }
3231 cursor += ret;
3232 ++i;
3233 }
3234 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3235 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003236 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003237 return ret >= 0;
3238}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003239
Haynes Mathew George569b7482017-05-08 14:44:27 -07003240static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3241{
3242 struct stream_out *out = (struct stream_out *)stream;
3243 struct str_parms *query = str_parms_create_str(keys);
3244 char *str;
3245 struct str_parms *reply = str_parms_create();
3246 bool replied = false;
3247 ALOGV("%s: enter: keys - %s", __func__, keys);
3248
3249 replied |= stream_get_parameter_channels(query, reply,
3250 &out->supported_channel_masks[0]);
3251 replied |= stream_get_parameter_formats(query, reply,
3252 &out->supported_formats[0]);
3253 replied |= stream_get_parameter_rates(query, reply,
3254 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003255 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 str = str_parms_to_str(reply);
3257 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003258 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 }
3260 str_parms_destroy(query);
3261 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003262 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 return str;
3264}
3265
3266static uint32_t out_get_latency(const struct audio_stream_out *stream)
3267{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003268 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003270 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3273 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003274 else if ((out->realtime) ||
3275 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003276 // since the buffer won't be filled up faster than realtime,
3277 // return a smaller number
3278 period_ms = (out->af_period_multiplier * out->config.period_size *
3279 1000) / (out->config.rate);
3280 hw_delay = platform_render_latency(out->usecase)/1000;
3281 return period_ms + hw_delay;
3282 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003283
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003284 latency = (out->config.period_count * out->config.period_size * 1000) /
3285 (out->config.rate);
3286
3287 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3288 latency += audio_extn_a2dp_get_encoder_latency();
3289
3290 return latency;
3291}
3292
3293static int set_compr_volume(struct audio_stream_out *stream, float left,
3294 float right)
3295{
3296 struct stream_out *out = (struct stream_out *)stream;
3297 int volume[2];
3298 char mixer_ctl_name[128];
3299 struct audio_device *adev = out->dev;
3300 struct mixer_ctl *ctl;
3301 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3302 PCM_PLAYBACK);
3303
3304 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3305 "Compress Playback %d Volume", pcm_device_id);
3306 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3307 if (!ctl) {
3308 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3309 __func__, mixer_ctl_name);
3310 return -EINVAL;
3311 }
3312 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3313 __func__, mixer_ctl_name, left, right);
3314 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3315 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3316 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3317
3318 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319}
3320
3321static int out_set_volume(struct audio_stream_out *stream, float left,
3322 float right)
3323{
Eric Laurenta9024de2013-04-04 09:19:12 -07003324 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003325 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003327 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003328 /* only take left channel into account: the API is for stereo anyway */
3329 out->muted = (left == 0.0f);
3330 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003331 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003332 pthread_mutex_lock(&out->compr_mute_lock);
3333 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3334 if (!out->a2dp_compress_mute)
3335 ret = set_compr_volume(stream, left, right);
3336 out->volume_l = left;
3337 out->volume_r = right;
3338 pthread_mutex_unlock(&out->compr_mute_lock);
3339 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003340 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003341 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3342 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3343 if (!out->standby) {
3344 // if in standby, cached volume will be sent after stream is opened
3345 audio_extn_utils_send_app_type_gain(out->dev,
3346 out->app_type_cfg.app_type,
3347 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003348 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003349 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003350 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 return -ENOSYS;
3353}
3354
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003355// note: this call is safe only if the stream_cb is
3356// removed first in close_output_stream (as is done now).
3357static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3358{
3359 if (!stream || !parms)
3360 return;
3361
3362 struct stream_out *out = (struct stream_out *)stream;
3363 struct audio_device *adev = out->dev;
3364
3365 card_status_t status;
3366 int card;
3367 if (parse_snd_card_status(parms, &card, &status) < 0)
3368 return;
3369
3370 pthread_mutex_lock(&adev->lock);
3371 bool valid_cb = (card == adev->snd_card);
3372 pthread_mutex_unlock(&adev->lock);
3373
3374 if (!valid_cb)
3375 return;
3376
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003377 lock_output_stream(out);
3378 if (out->card_status != status)
3379 out->card_status = status;
3380 pthread_mutex_unlock(&out->lock);
3381
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003382 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3383 use_case_table[out->usecase],
3384 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3385
3386 if (status == CARD_STATUS_OFFLINE)
3387 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003388
3389 return;
3390}
3391
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003392#ifdef NO_AUDIO_OUT
3393static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003394 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003395{
3396 struct stream_out *out = (struct stream_out *)stream;
3397
3398 /* No Output device supported other than BT for playback.
3399 * Sleep for the amount of buffer duration
3400 */
Eric Laurenta1478072015-09-21 17:21:52 -07003401 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003402 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3403 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003404 out_get_sample_rate(&out->stream.common));
3405 pthread_mutex_unlock(&out->lock);
3406 return bytes;
3407}
3408#endif
3409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3411 size_t bytes)
3412{
3413 struct stream_out *out = (struct stream_out *)stream;
3414 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003415 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003416 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417
Eric Laurenta1478072015-09-21 17:21:52 -07003418 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003419 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003420 const size_t frame_size = audio_stream_out_frame_size(stream);
3421 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003422
Eric Laurent0e46adf2016-12-16 12:49:24 -08003423 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3424 error_code = ERROR_CODE_WRITE;
3425 goto exit;
3426 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003427
3428 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3429 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003430 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003431 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3432 ret = -EIO;
3433 goto exit;
3434 }
3435 }
3436 }
3437
Andy Hung572633e2019-02-19 11:58:24 -08003438 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003439 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003440 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003441 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3442
Eric Laurent150dbfe2013-02-27 14:31:02 -08003443 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003445
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003446 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003448 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003449 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450 goto exit;
3451 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003452
vivek mehta40125092017-08-21 18:48:51 -07003453 // after standby always force set last known cal step
3454 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3455 ALOGD("%s: retry previous failed cal level set", __func__);
3456 send_gain_dep_calibration_l();
3457 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003458
Andy Hung241e36f2019-02-19 12:00:38 -08003459 // log startup time in ms.
3460 simple_stats_log(
3461 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003462 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003466 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003467 if (out->send_new_metadata) {
3468 ALOGVV("send new gapless metadata");
3469 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3470 out->send_new_metadata = 0;
3471 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003472 unsigned int avail;
3473 struct timespec tstamp;
3474 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3475 /* Do not limit write size if the available frames count is unknown */
3476 if (ret != 0) {
3477 avail = bytes;
3478 }
3479 if (avail == 0) {
3480 ret = 0;
3481 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003482 // check for compressed format underrun, essentially an empty buffer check
3483 // for a lack of better measurement.
3484 if (!was_in_standby && avail == out->kernel_buffer_size) {
3485 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3486 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3487 }
3488
Eric Laurentb49b3f62016-02-29 17:59:49 -08003489 if (avail > bytes) {
3490 avail = bytes;
3491 }
3492 ret = compress_write(out->compr, buffer, avail);
3493 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3494 __func__, avail, ret);
3495 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003496
Eric Laurent6e895242013-09-05 16:10:57 -07003497 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003498 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3499 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003500 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003501 compress_start(out->compr);
3502 out->playback_started = 1;
3503 out->offload_state = OFFLOAD_STATE_PLAYING;
3504 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003505 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003506 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003507 } else {
3508 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003509 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003510 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003511 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 return ret;
3513 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003514 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003516 size_t bytes_to_write = bytes;
3517
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003518 if (out->muted)
3519 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003520 // FIXME: this can be removed once audio flinger mixer supports mono output
Vignesh Kulothungan3ff76892019-06-05 11:49:28 -07003521 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP ||
3522 out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3523 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003524 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3525 int16_t *src = (int16_t *)buffer;
3526 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003527
Eric Laurentad2dde92017-09-20 18:27:31 -07003528 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3529 out->format != AUDIO_FORMAT_PCM_16_BIT,
3530 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003531
Eric Laurentad2dde92017-09-20 18:27:31 -07003532 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3533 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3534 }
3535 bytes_to_write /= 2;
3536 }
Andy Hung572633e2019-02-19 11:58:24 -08003537
3538 // Note: since out_get_presentation_position() is called alternating with out_write()
3539 // by AudioFlinger, we can check underruns using the prior timestamp read.
3540 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3541 if (out->last_fifo_valid) {
3542 // compute drain to see if there is an underrun.
3543 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3544 const int64_t frames_by_time =
3545 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3546 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3547
3548 if (underrun > 0) {
3549 simple_stats_log(&out->fifo_underruns, underrun);
3550
3551 ALOGW("%s: underrun(%lld) "
3552 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3553 __func__,
3554 (long long)out->fifo_underruns.n,
3555 (long long)frames_by_time,
3556 (long long)out->last_fifo_frames_remaining);
3557 }
3558 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3559 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003560
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003561 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003562 request_out_focus(out, ns);
3563
3564 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003565 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003566 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003567 } else {
3568 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3569 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3570 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3571 size_t frame_size = channel_count * bytes_per_sample;
3572 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003573
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003574 bool force_haptic_path =
3575 property_get_bool("vendor.audio.test_haptic", false);
3576
3577 // extract Haptics data from Audio buffer
3578 bool alloc_haptic_buffer = false;
3579 int haptic_channel_count = adev->haptics_config.channels;
3580 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3581 size_t audio_frame_size = frame_size - haptic_frame_size;
3582 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3583
3584 if (adev->haptic_buffer == NULL) {
3585 alloc_haptic_buffer = true;
3586 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3587 free(adev->haptic_buffer);
3588 adev->haptic_buffer_size = 0;
3589 alloc_haptic_buffer = true;
3590 }
3591
3592 if (alloc_haptic_buffer) {
3593 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3594 adev->haptic_buffer_size = total_haptic_buffer_size;
3595 }
3596
3597 size_t src_index = 0, aud_index = 0, hap_index = 0;
3598 uint8_t *audio_buffer = (uint8_t *)buffer;
3599 uint8_t *haptic_buffer = adev->haptic_buffer;
3600
3601 // This is required for testing only. This works for stereo data only.
3602 // One channel is fed to audio stream and other to haptic stream for testing.
3603 if (force_haptic_path) {
3604 audio_frame_size = haptic_frame_size = bytes_per_sample;
3605 }
3606
3607 for (size_t i = 0; i < frame_count; i++) {
3608 for (size_t j = 0; j < audio_frame_size; j++)
3609 audio_buffer[aud_index++] = audio_buffer[src_index++];
3610
3611 for (size_t j = 0; j < haptic_frame_size; j++)
3612 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3613 }
3614
3615 // This is required for testing only.
3616 // Discard haptic channel data.
3617 if (force_haptic_path) {
3618 src_index += haptic_frame_size;
3619 }
3620
3621 // write to audio pipeline
3622 ret = pcm_write(out->pcm,
3623 (void *)audio_buffer,
3624 frame_count * audio_frame_size);
3625
3626 // write to haptics pipeline
3627 if (adev->haptic_pcm)
3628 ret = pcm_write(adev->haptic_pcm,
3629 (void *)adev->haptic_buffer,
3630 frame_count * haptic_frame_size);
3631
3632 } else {
3633 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3634 }
3635 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003636 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003637 } else {
3638 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003639 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 }
3641
3642exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003643 // For PCM we always consume the buffer and return #bytes regardless of ret.
3644 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003645 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003646 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003647 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003648
Andy Hung7401c7c2016-09-21 12:41:21 -07003649 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003650 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003651 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3652 ALOGE_IF(out->pcm != NULL,
3653 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003654 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003655 // usleep not guaranteed for values over 1 second but we don't limit here.
3656 }
3657 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 pthread_mutex_unlock(&out->lock);
3660
3661 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003662 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003663 if (sleeptime_us != 0)
3664 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 }
3666 return bytes;
3667}
3668
3669static int out_get_render_position(const struct audio_stream_out *stream,
3670 uint32_t *dsp_frames)
3671{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 struct stream_out *out = (struct stream_out *)stream;
3673 *dsp_frames = 0;
3674 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003675 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003677 unsigned long frames = 0;
3678 // TODO: check return value
3679 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3680 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681 ALOGVV("%s rendered frames %d sample_rate %d",
3682 __func__, *dsp_frames, out->sample_rate);
3683 }
3684 pthread_mutex_unlock(&out->lock);
3685 return 0;
3686 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003687 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688}
3689
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003690static int out_add_audio_effect(const struct audio_stream *stream __unused,
3691 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692{
3693 return 0;
3694}
3695
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003696static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3697 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698{
3699 return 0;
3700}
3701
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003702static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3703 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003705 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706}
3707
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003708static int out_get_presentation_position(const struct audio_stream_out *stream,
3709 uint64_t *frames, struct timespec *timestamp)
3710{
3711 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003712 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003713 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003714
Eric Laurenta1478072015-09-21 17:21:52 -07003715 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003716
Eric Laurent949a0892013-09-20 09:20:13 -07003717 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3718 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003719 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003720 compress_get_tstamp(out->compr, &dsp_frames,
3721 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003722 // Adjustment accounts for A2DP encoder latency with offload usecases
3723 // Note: Encoder latency is returned in ms.
3724 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3725 unsigned long offset =
3726 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3727 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3728 }
Eric Laurent949a0892013-09-20 09:20:13 -07003729 ALOGVV("%s rendered frames %ld sample_rate %d",
3730 __func__, dsp_frames, out->sample_rate);
3731 *frames = dsp_frames;
3732 ret = 0;
3733 /* this is the best we can do */
3734 clock_gettime(CLOCK_MONOTONIC, timestamp);
3735 }
3736 } else {
3737 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003738 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003739 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003740
3741 // pcm_get_htimestamp() computes the available frames by comparing
3742 // the alsa driver hw_ptr and the appl_ptr levels.
3743 // In underrun, the hw_ptr may keep running and report an excessively
3744 // large number available number.
3745 if (avail > out->kernel_buffer_size) {
3746 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3747 __func__, avail, out->kernel_buffer_size);
3748 avail = out->kernel_buffer_size;
3749 out->last_fifo_frames_remaining = 0;
3750 } else {
3751 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3752 }
3753 out->last_fifo_valid = true;
3754 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3755
3756 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3757
3758 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3759 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3760
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003761 // This adjustment accounts for buffering after app processor.
3762 // It is based on estimated DSP latency per use case, rather than exact.
3763 signed_frames -=
3764 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3765
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003766 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3767 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3768 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3769 signed_frames -=
3770 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3771 }
3772
Eric Laurent949a0892013-09-20 09:20:13 -07003773 // It would be unusual for this value to be negative, but check just in case ...
3774 if (signed_frames >= 0) {
3775 *frames = signed_frames;
3776 ret = 0;
3777 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003778 }
3779 }
3780 }
3781
3782 pthread_mutex_unlock(&out->lock);
3783
3784 return ret;
3785}
3786
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003787static int out_set_callback(struct audio_stream_out *stream,
3788 stream_callback_t callback, void *cookie)
3789{
3790 struct stream_out *out = (struct stream_out *)stream;
3791
3792 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003793 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003794 out->offload_callback = callback;
3795 out->offload_cookie = cookie;
3796 pthread_mutex_unlock(&out->lock);
3797 return 0;
3798}
3799
3800static int out_pause(struct audio_stream_out* stream)
3801{
3802 struct stream_out *out = (struct stream_out *)stream;
3803 int status = -ENOSYS;
3804 ALOGV("%s", __func__);
3805 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003806 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3808 status = compress_pause(out->compr);
3809 out->offload_state = OFFLOAD_STATE_PAUSED;
3810 }
3811 pthread_mutex_unlock(&out->lock);
3812 }
3813 return status;
3814}
3815
3816static int out_resume(struct audio_stream_out* stream)
3817{
3818 struct stream_out *out = (struct stream_out *)stream;
3819 int status = -ENOSYS;
3820 ALOGV("%s", __func__);
3821 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3822 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003823 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003824 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3825 status = compress_resume(out->compr);
3826 out->offload_state = OFFLOAD_STATE_PLAYING;
3827 }
3828 pthread_mutex_unlock(&out->lock);
3829 }
3830 return status;
3831}
3832
3833static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3834{
3835 struct stream_out *out = (struct stream_out *)stream;
3836 int status = -ENOSYS;
3837 ALOGV("%s", __func__);
3838 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003839 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3841 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3842 else
3843 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3844 pthread_mutex_unlock(&out->lock);
3845 }
3846 return status;
3847}
3848
3849static int out_flush(struct audio_stream_out* stream)
3850{
3851 struct stream_out *out = (struct stream_out *)stream;
3852 ALOGV("%s", __func__);
3853 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003854 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003855 stop_compressed_output_l(out);
3856 pthread_mutex_unlock(&out->lock);
3857 return 0;
3858 }
3859 return -ENOSYS;
3860}
3861
Eric Laurent0e46adf2016-12-16 12:49:24 -08003862static int out_stop(const struct audio_stream_out* stream)
3863{
3864 struct stream_out *out = (struct stream_out *)stream;
3865 struct audio_device *adev = out->dev;
3866 int ret = -ENOSYS;
3867
3868 ALOGV("%s", __func__);
3869 pthread_mutex_lock(&adev->lock);
3870 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3871 out->playback_started && out->pcm != NULL) {
3872 pcm_stop(out->pcm);
3873 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003874 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003875 }
3876 pthread_mutex_unlock(&adev->lock);
3877 return ret;
3878}
3879
3880static int out_start(const struct audio_stream_out* stream)
3881{
3882 struct stream_out *out = (struct stream_out *)stream;
3883 struct audio_device *adev = out->dev;
3884 int ret = -ENOSYS;
3885
3886 ALOGV("%s", __func__);
3887 pthread_mutex_lock(&adev->lock);
3888 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3889 !out->playback_started && out->pcm != NULL) {
3890 ret = start_output_stream(out);
3891 if (ret == 0) {
3892 out->playback_started = true;
3893 }
3894 }
3895 pthread_mutex_unlock(&adev->lock);
3896 return ret;
3897}
3898
Phil Burkbc991042017-02-24 08:06:44 -08003899/*
3900 * Modify config->period_count based on min_size_frames
3901 */
3902static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3903{
3904 int periodCountRequested = (min_size_frames + config->period_size - 1)
3905 / config->period_size;
3906 int periodCount = MMAP_PERIOD_COUNT_MIN;
3907
3908 ALOGV("%s original config.period_size = %d config.period_count = %d",
3909 __func__, config->period_size, config->period_count);
3910
3911 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3912 periodCount *= 2;
3913 }
3914 config->period_count = periodCount;
3915
3916 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3917}
3918
Phil Burk51e6bc42019-03-25 10:23:35 -07003919// Read offset for the positional timestamp from a persistent vendor property.
3920// This is to workaround apparent inaccuracies in the timing information that
3921// is used by the AAudio timing model. The inaccuracies can cause glitches.
3922static int64_t get_mmap_out_time_offset() {
3923 const int32_t kDefaultOffsetMicros = 0;
3924 int32_t mmap_time_offset_micros = property_get_int32(
3925 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3926 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3927 return mmap_time_offset_micros * (int64_t)1000;
3928}
3929
Eric Laurent0e46adf2016-12-16 12:49:24 -08003930static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3931 int32_t min_size_frames,
3932 struct audio_mmap_buffer_info *info)
3933{
3934 struct stream_out *out = (struct stream_out *)stream;
3935 struct audio_device *adev = out->dev;
3936 int ret = 0;
3937 unsigned int offset1;
3938 unsigned int frames1;
3939 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003940 uint32_t mmap_size;
3941 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003942
3943 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003944 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003945 pthread_mutex_lock(&adev->lock);
3946
3947 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003948 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003949 ret = -EINVAL;
3950 goto exit;
3951 }
3952 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003953 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003954 ret = -ENOSYS;
3955 goto exit;
3956 }
3957 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3958 if (out->pcm_device_id < 0) {
3959 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3960 __func__, out->pcm_device_id, out->usecase);
3961 ret = -EINVAL;
3962 goto exit;
3963 }
Phil Burkbc991042017-02-24 08:06:44 -08003964
3965 adjust_mmap_period_count(&out->config, min_size_frames);
3966
Eric Laurent0e46adf2016-12-16 12:49:24 -08003967 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3968 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3969 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3970 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3971 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3972 step = "open";
3973 ret = -ENODEV;
3974 goto exit;
3975 }
3976 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3977 if (ret < 0) {
3978 step = "begin";
3979 goto exit;
3980 }
3981 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003982 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003983 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003984 ret = platform_get_mmap_data_fd(adev->platform,
3985 out->pcm_device_id, 0 /*playback*/,
3986 &info->shared_memory_fd,
3987 &mmap_size);
3988 if (ret < 0) {
3989 // Fall back to non exclusive mode
3990 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3991 } else {
3992 if (mmap_size < buffer_size) {
3993 step = "mmap";
3994 goto exit;
3995 }
3996 // FIXME: indicate exclusive mode support by returning a negative buffer size
3997 info->buffer_size_frames *= -1;
3998 }
3999 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004000
4001 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
4002 if (ret < 0) {
4003 step = "commit";
4004 goto exit;
4005 }
Phil Burkbc991042017-02-24 08:06:44 -08004006
Phil Burk51e6bc42019-03-25 10:23:35 -07004007 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
4008
Phil Burkbc991042017-02-24 08:06:44 -08004009 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004010 ret = 0;
4011
4012 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4013 __func__, info->shared_memory_address, info->buffer_size_frames);
4014
4015exit:
4016 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004017 if (out->pcm == NULL) {
4018 ALOGE("%s: %s - %d", __func__, step, ret);
4019 } else {
4020 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004021 pcm_close(out->pcm);
4022 out->pcm = NULL;
4023 }
4024 }
4025 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004026 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004027 return ret;
4028}
4029
4030static int out_get_mmap_position(const struct audio_stream_out *stream,
4031 struct audio_mmap_position *position)
4032{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004033 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004034 struct stream_out *out = (struct stream_out *)stream;
4035 ALOGVV("%s", __func__);
4036 if (position == NULL) {
4037 return -EINVAL;
4038 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004039 lock_output_stream(out);
4040 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
4041 out->pcm == NULL) {
4042 ret = -ENOSYS;
4043 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004044 }
4045
4046 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004047 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004048 if (ret < 0) {
4049 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004050 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004051 }
Phil Burk51e6bc42019-03-25 10:23:35 -07004052 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4053 + out->mmap_time_offset_nanos;
4054
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004055exit:
4056 pthread_mutex_unlock(&out->lock);
4057 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004058}
4059
4060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061/** audio_stream_in implementation **/
4062static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4063{
4064 struct stream_in *in = (struct stream_in *)stream;
4065
4066 return in->config.rate;
4067}
4068
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004069static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070{
4071 return -ENOSYS;
4072}
4073
4074static size_t in_get_buffer_size(const struct audio_stream *stream)
4075{
4076 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004077 return in->config.period_size * in->af_period_multiplier *
4078 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079}
4080
4081static uint32_t in_get_channels(const struct audio_stream *stream)
4082{
4083 struct stream_in *in = (struct stream_in *)stream;
4084
4085 return in->channel_mask;
4086}
4087
vivek mehta4ed66e62016-04-15 23:33:34 -07004088static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089{
vivek mehta4ed66e62016-04-15 23:33:34 -07004090 struct stream_in *in = (struct stream_in *)stream;
4091 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092}
4093
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004094static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095{
4096 return -ENOSYS;
4097}
4098
4099static int in_standby(struct audio_stream *stream)
4100{
4101 struct stream_in *in = (struct stream_in *)stream;
4102 struct audio_device *adev = in->dev;
4103 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08004104 bool do_stop = true;
4105
Eric Laurent994a6932013-07-17 11:51:42 -07004106 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07004107
4108 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004109
Carter Hsu968d6812019-06-12 21:36:14 +08004110 if (!in->standby && (in->flags & AUDIO_INPUT_FLAG_HW_HOTWORD)) {
Joe Onorato188b6222016-03-01 11:02:27 -08004111 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004112 audio_extn_sound_trigger_stop_lab(in);
4113 in->standby = true;
4114 }
4115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004117 if (adev->adm_deregister_stream)
4118 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4119
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004120 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004122 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08004123 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004124 in->capture_started = false;
4125 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004126 if (in->pcm) {
4127 pcm_close(in->pcm);
4128 in->pcm = NULL;
4129 }
Carter Hsub0c91482019-05-14 18:50:52 +08004130
4131 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
4132 adev->enable_voicerx = false;
4133
Phil Burkbc991042017-02-24 08:06:44 -08004134 if (do_stop) {
4135 status = stop_input_stream(in);
4136 }
Carter Hsub0c91482019-05-14 18:50:52 +08004137
Eric Laurent150dbfe2013-02-27 14:31:02 -08004138 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 }
4140 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004141 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 return status;
4143}
4144
Andy Hungd13f0d32017-06-12 13:58:37 -07004145static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004146{
Andy Hungd13f0d32017-06-12 13:58:37 -07004147 struct stream_in *in = (struct stream_in *)stream;
4148
4149 // We try to get the lock for consistency,
4150 // but it isn't necessary for these variables.
4151 // If we're not in standby, we may be blocked on a read.
4152 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4153 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4154 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4155 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4156
Andy Hung241e36f2019-02-19 12:00:38 -08004157 char buffer[256]; // for statistics formatting
4158 if (in->start_latency_ms.n > 0) {
4159 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4160 dprintf(fd, " Start latency ms: %s\n", buffer);
4161 }
4162
Andy Hungd13f0d32017-06-12 13:58:37 -07004163 if (locked) {
4164 pthread_mutex_unlock(&in->lock);
4165 }
4166
4167 // dump error info
4168 (void)error_log_dump(
4169 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 return 0;
4171}
4172
4173static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4174{
4175 struct stream_in *in = (struct stream_in *)stream;
4176 struct audio_device *adev = in->dev;
4177 struct str_parms *parms;
4178 char *str;
4179 char value[32];
4180 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004181 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182
Eric Laurent994a6932013-07-17 11:51:42 -07004183 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 parms = str_parms_create_str(kvpairs);
4185
4186 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4187
Eric Laurenta1478072015-09-21 17:21:52 -07004188 lock_input_stream(in);
4189
Eric Laurent150dbfe2013-02-27 14:31:02 -08004190 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 if (ret >= 0) {
4192 val = atoi(value);
4193 /* no audio source uses val == 0 */
4194 if ((in->source != val) && (val != 0)) {
4195 in->source = val;
4196 }
4197 }
4198
4199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 if (ret >= 0) {
4202 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004203 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004204
4205 // Workaround: If routing to an non existing usb device, fail gracefully
4206 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004207 int card;
4208 if (audio_is_usb_in_device(val) &&
4209 (card = get_alive_usb_card(parms)) >= 0) {
4210
4211 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004212 status = -ENOSYS;
4213 } else {
4214
4215 in->device = val;
4216 /* If recording is in progress, change the tx device to new device */
4217 if (!in->standby) {
4218 ALOGV("update input routing change");
4219 // inform adm before actual routing to prevent glitches.
4220 if (adev->adm_on_routing_change) {
4221 adev->adm_on_routing_change(adev->adm_data,
4222 in->capture_handle);
4223 }
4224 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004225 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 }
4228 }
4229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004231 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232
4233 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004234 ALOGV("%s: exit: status(%d)", __func__, status);
4235 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236}
4237
Haynes Mathew George569b7482017-05-08 14:44:27 -07004238static char* in_get_parameters(const struct audio_stream *stream,
4239 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004241 struct stream_in *in = (struct stream_in *)stream;
4242 struct str_parms *query = str_parms_create_str(keys);
4243 char *str;
4244 struct str_parms *reply = str_parms_create();
4245 bool replied = false;
4246
4247 ALOGV("%s: enter: keys - %s", __func__, keys);
4248 replied |= stream_get_parameter_channels(query, reply,
4249 &in->supported_channel_masks[0]);
4250 replied |= stream_get_parameter_formats(query, reply,
4251 &in->supported_formats[0]);
4252 replied |= stream_get_parameter_rates(query, reply,
4253 &in->supported_sample_rates[0]);
4254 if (replied) {
4255 str = str_parms_to_str(reply);
4256 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004257 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004258 }
4259 str_parms_destroy(query);
4260 str_parms_destroy(reply);
4261 ALOGV("%s: exit: returns - %s", __func__, str);
4262 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004263}
4264
Eric Laurent51f3c662018-04-10 18:21:34 -07004265static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266{
Eric Laurent51f3c662018-04-10 18:21:34 -07004267 struct stream_in *in = (struct stream_in *)stream;
4268 char mixer_ctl_name[128];
4269 struct mixer_ctl *ctl;
4270 int ctl_value;
4271
4272 ALOGV("%s: gain %f", __func__, gain);
4273
4274 if (stream == NULL)
4275 return -EINVAL;
4276
4277 /* in_set_gain() only used to silence MMAP capture for now */
4278 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4279 return -ENOSYS;
4280
4281 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4282
4283 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4284 if (!ctl) {
4285 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4286 __func__, mixer_ctl_name);
4287 return -ENOSYS;
4288 }
4289
4290 if (gain < RECORD_GAIN_MIN)
4291 gain = RECORD_GAIN_MIN;
4292 else if (gain > RECORD_GAIN_MAX)
4293 gain = RECORD_GAIN_MAX;
4294 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4295
4296 mixer_ctl_set_value(ctl, 0, ctl_value);
4297 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298}
4299
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004300static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4301{
4302 if (!stream || !parms)
4303 return;
4304
4305 struct stream_in *in = (struct stream_in *)stream;
4306 struct audio_device *adev = in->dev;
4307
4308 card_status_t status;
4309 int card;
4310 if (parse_snd_card_status(parms, &card, &status) < 0)
4311 return;
4312
4313 pthread_mutex_lock(&adev->lock);
4314 bool valid_cb = (card == adev->snd_card);
4315 pthread_mutex_unlock(&adev->lock);
4316
4317 if (!valid_cb)
4318 return;
4319
4320 lock_input_stream(in);
4321 if (in->card_status != status)
4322 in->card_status = status;
4323 pthread_mutex_unlock(&in->lock);
4324
4325 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4326 use_case_table[in->usecase],
4327 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4328
4329 // a better solution would be to report error back to AF and let
4330 // it put the stream to standby
4331 if (status == CARD_STATUS_OFFLINE)
4332 in_standby(&in->stream.common);
4333
4334 return;
4335}
4336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4338 size_t bytes)
4339{
4340 struct stream_in *in = (struct stream_in *)stream;
4341 struct audio_device *adev = in->dev;
4342 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004343 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004344 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345
Eric Laurenta1478072015-09-21 17:21:52 -07004346 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004347 const size_t frame_size = audio_stream_in_frame_size(stream);
4348 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004349
Carter Hsu968d6812019-06-12 21:36:14 +08004350 if (in->flags & AUDIO_INPUT_FLAG_HW_HOTWORD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004351 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004352 /* Read from sound trigger HAL */
4353 audio_extn_sound_trigger_read(in, buffer, bytes);
4354 pthread_mutex_unlock(&in->lock);
4355 return bytes;
4356 }
4357
Eric Laurent0e46adf2016-12-16 12:49:24 -08004358 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4359 ret = -ENOSYS;
4360 goto exit;
4361 }
4362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004364 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4365
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004366 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004368 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 goto exit;
4371 }
4372 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004373
4374 // log startup time in ms.
4375 simple_stats_log(
4376 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378
Andy Hungd13f0d32017-06-12 13:58:37 -07004379 // errors that occur here are read errors.
4380 error_code = ERROR_CODE_READ;
4381
Haynes Mathew George03c40102016-01-29 17:57:48 -08004382 //what's the duration requested by the client?
4383 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4384 in->config.rate;
4385 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004386
Haynes Mathew George03c40102016-01-29 17:57:48 -08004387 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004389 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004390 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004391 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004392 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004393 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004394 if (ret < 0) {
4395 ALOGE("Failed to read w/err %s", strerror(errno));
4396 ret = -errno;
4397 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004398 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4399 if (bytes % 4 == 0) {
4400 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4401 int_buf_stream = buffer;
4402 for (size_t itt=0; itt < bytes/4 ; itt++) {
4403 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004404 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004405 } else {
4406 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4407 ret = -EINVAL;
4408 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004409 }
4410 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 }
4412
Haynes Mathew George03c40102016-01-29 17:57:48 -08004413 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 /*
4416 * Instead of writing zeroes here, we could trust the hardware
4417 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004418 * 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 -08004419 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004420 if (ret == 0 && adev->mic_muted &&
4421 !voice_is_in_call_rec_stream(in) &&
4422 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004424 in->frames_muted += frames;
4425 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426
4427exit:
4428 pthread_mutex_unlock(&in->lock);
4429
4430 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004431 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 in_standby(&in->stream.common);
4433 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004434 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004435 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004436 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004437 }
4438 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004439 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440 }
4441 return bytes;
4442}
4443
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004444static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445{
4446 return 0;
4447}
4448
Andy Hung6ebe5962016-01-15 17:46:57 -08004449static int in_get_capture_position(const struct audio_stream_in *stream,
4450 int64_t *frames, int64_t *time)
4451{
4452 if (stream == NULL || frames == NULL || time == NULL) {
4453 return -EINVAL;
4454 }
4455 struct stream_in *in = (struct stream_in *)stream;
4456 int ret = -ENOSYS;
4457
4458 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004459 // note: ST sessions do not close the alsa pcm driver synchronously
4460 // on standby. Therefore, we may return an error even though the
4461 // pcm stream is still opened.
4462 if (in->standby) {
Carter Hsu968d6812019-06-12 21:36:14 +08004463 ALOGE_IF(in->pcm != NULL && !(in->flags & AUDIO_INPUT_FLAG_HW_HOTWORD),
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004464 "%s stream in standby but pcm not NULL for non ST session", __func__);
4465 goto exit;
4466 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004467 if (in->pcm) {
4468 struct timespec timestamp;
4469 unsigned int avail;
4470 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4471 *frames = in->frames_read + avail;
4472 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4473 ret = 0;
4474 }
4475 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004476exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004477 pthread_mutex_unlock(&in->lock);
4478 return ret;
4479}
4480
Carter Hsub0c91482019-05-14 18:50:52 +08004481static int in_update_effect_list(bool add, effect_handle_t effect,
4482 struct listnode *head)
4483{
4484 struct listnode *node;
4485 struct in_effect_list *elist = NULL;
4486 struct in_effect_list *target = NULL;
4487 int ret = 0;
4488
4489 if (!head)
4490 return ret;
4491
4492 list_for_each(node, head) {
4493 elist = node_to_item(node, struct in_effect_list, list);
4494 if (elist->handle == effect) {
4495 target = elist;
4496 break;
4497 }
4498 }
4499
4500 if (add) {
4501 if (target) {
4502 ALOGD("effect %p already exist", effect);
4503 return ret;
4504 }
4505
4506 target = (struct in_effect_list *)
4507 calloc(1, sizeof(struct in_effect_list));
4508
4509 if (!target) {
4510 ALOGE("%s:fail to allocate memory", __func__);
4511 return -ENOMEM;
4512 }
4513
4514 target->handle = effect;
4515 list_add_tail(head, &target->list);
4516 } else {
4517 if (target) {
4518 list_remove(&target->list);
4519 free(target);
4520 }
4521 }
4522
4523 return ret;
4524}
4525
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004526static int add_remove_audio_effect(const struct audio_stream *stream,
4527 effect_handle_t effect,
4528 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004530 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004531 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004532 int status = 0;
4533 effect_descriptor_t desc;
4534
4535 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004536 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4537
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004538 if (status != 0)
4539 return status;
4540
Eric Laurenta1478072015-09-21 17:21:52 -07004541 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004542 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004543 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004544 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004545 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004546 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsub0c91482019-05-14 18:50:52 +08004547
4548 in_update_effect_list(enable, effect, &in->aec_list);
4549 enable = !list_empty(&in->aec_list);
4550 if (enable == in->enable_aec)
4551 goto exit;
4552
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004553 in->enable_aec = enable;
Carter Hsub0c91482019-05-14 18:50:52 +08004554 ALOGD("AEC enable %d", enable);
4555
vivek mehta733c1df2016-04-04 15:09:24 -07004556 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4557 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4558 adev->enable_voicerx = enable;
4559 struct audio_usecase *usecase;
4560 struct listnode *node;
4561 list_for_each(node, &adev->usecase_list) {
4562 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004563 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004564 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004565 }
4566 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004567 if (!in->standby
4568 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004569 select_devices(in->dev, in->usecase);
4570 }
Carter Hsub0c91482019-05-14 18:50:52 +08004571 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
4572
4573 in_update_effect_list(enable, effect, &in->ns_list);
4574 enable = !list_empty(&in->ns_list);
4575 if (enable == in->enable_ns)
4576 goto exit;
4577
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004578 in->enable_ns = enable;
Carter Hsub0c91482019-05-14 18:50:52 +08004579 ALOGD("NS enable %d", enable);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004580 if (!in->standby) {
4581 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4582 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4583 select_devices(in->dev, in->usecase);
4584 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004585 }
Carter Hsub0c91482019-05-14 18:50:52 +08004586exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004587 pthread_mutex_unlock(&in->dev->lock);
4588 pthread_mutex_unlock(&in->lock);
4589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 return 0;
4591}
4592
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004593static int in_add_audio_effect(const struct audio_stream *stream,
4594 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595{
Eric Laurent994a6932013-07-17 11:51:42 -07004596 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004597 return add_remove_audio_effect(stream, effect, true);
4598}
4599
4600static int in_remove_audio_effect(const struct audio_stream *stream,
4601 effect_handle_t effect)
4602{
Eric Laurent994a6932013-07-17 11:51:42 -07004603 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004604 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605}
4606
Eric Laurent0e46adf2016-12-16 12:49:24 -08004607static int in_stop(const struct audio_stream_in* stream)
4608{
4609 struct stream_in *in = (struct stream_in *)stream;
4610 struct audio_device *adev = in->dev;
4611
4612 int ret = -ENOSYS;
4613 ALOGV("%s", __func__);
4614 pthread_mutex_lock(&adev->lock);
4615 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4616 in->capture_started && in->pcm != NULL) {
4617 pcm_stop(in->pcm);
4618 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004619 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004620 }
4621 pthread_mutex_unlock(&adev->lock);
4622 return ret;
4623}
4624
4625static int in_start(const struct audio_stream_in* stream)
4626{
4627 struct stream_in *in = (struct stream_in *)stream;
4628 struct audio_device *adev = in->dev;
4629 int ret = -ENOSYS;
4630
4631 ALOGV("%s in %p", __func__, in);
4632 pthread_mutex_lock(&adev->lock);
4633 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4634 !in->capture_started && in->pcm != NULL) {
4635 if (!in->capture_started) {
4636 ret = start_input_stream(in);
4637 if (ret == 0) {
4638 in->capture_started = true;
4639 }
4640 }
4641 }
4642 pthread_mutex_unlock(&adev->lock);
4643 return ret;
4644}
4645
Phil Burk8a6a1652019-03-25 10:15:59 -07004646// Read offset for the positional timestamp from a persistent vendor property.
4647// This is to workaround apparent inaccuracies in the timing information that
4648// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004649static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004650 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004651 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004652 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004653 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4654 return mmap_time_offset_micros * (int64_t)1000;
4655}
4656
Eric Laurent0e46adf2016-12-16 12:49:24 -08004657static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4658 int32_t min_size_frames,
4659 struct audio_mmap_buffer_info *info)
4660{
4661 struct stream_in *in = (struct stream_in *)stream;
4662 struct audio_device *adev = in->dev;
4663 int ret = 0;
4664 unsigned int offset1;
4665 unsigned int frames1;
4666 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004667 uint32_t mmap_size;
4668 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004669
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004670 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004671 pthread_mutex_lock(&adev->lock);
4672 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004673
Eric Laurent0e46adf2016-12-16 12:49:24 -08004674 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004675 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004676 ret = -EINVAL;
4677 goto exit;
4678 }
4679 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004680 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004681 ALOGV("%s in %p", __func__, in);
4682 ret = -ENOSYS;
4683 goto exit;
4684 }
4685 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4686 if (in->pcm_device_id < 0) {
4687 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4688 __func__, in->pcm_device_id, in->usecase);
4689 ret = -EINVAL;
4690 goto exit;
4691 }
Phil Burkbc991042017-02-24 08:06:44 -08004692
4693 adjust_mmap_period_count(&in->config, min_size_frames);
4694
Eric Laurent0e46adf2016-12-16 12:49:24 -08004695 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4696 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4697 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4698 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4699 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4700 step = "open";
4701 ret = -ENODEV;
4702 goto exit;
4703 }
4704
4705 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4706 if (ret < 0) {
4707 step = "begin";
4708 goto exit;
4709 }
4710 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004711 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004712 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004713 ret = platform_get_mmap_data_fd(adev->platform,
4714 in->pcm_device_id, 1 /*capture*/,
4715 &info->shared_memory_fd,
4716 &mmap_size);
4717 if (ret < 0) {
4718 // Fall back to non exclusive mode
4719 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4720 } else {
4721 if (mmap_size < buffer_size) {
4722 step = "mmap";
4723 goto exit;
4724 }
4725 // FIXME: indicate exclusive mode support by returning a negative buffer size
4726 info->buffer_size_frames *= -1;
4727 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004728
Haynes Mathew George96483a22017-03-28 14:52:47 -07004729 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004730
4731 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4732 if (ret < 0) {
4733 step = "commit";
4734 goto exit;
4735 }
4736
Phil Burkc4714fc2019-02-16 22:28:11 -08004737 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4738
Phil Burkbc991042017-02-24 08:06:44 -08004739 in->standby = false;
4740 ret = 0;
4741
Eric Laurent0e46adf2016-12-16 12:49:24 -08004742 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4743 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004744
4745exit:
4746 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004747 if (in->pcm == NULL) {
4748 ALOGE("%s: %s - %d", __func__, step, ret);
4749 } else {
4750 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004751 pcm_close(in->pcm);
4752 in->pcm = NULL;
4753 }
4754 }
4755 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004756 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004757 return ret;
4758}
4759
4760static int in_get_mmap_position(const struct audio_stream_in *stream,
4761 struct audio_mmap_position *position)
4762{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004763 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004764 struct stream_in *in = (struct stream_in *)stream;
4765 ALOGVV("%s", __func__);
4766 if (position == NULL) {
4767 return -EINVAL;
4768 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004769 lock_input_stream(in);
4770 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4771 in->pcm == NULL) {
4772 ret = -ENOSYS;
4773 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004774 }
4775 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004776 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004777 if (ret < 0) {
4778 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004779 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004780 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004781 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4782 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004783
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004784exit:
4785 pthread_mutex_unlock(&in->lock);
4786 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004787}
4788
jiabin8962a4d2018-03-19 18:21:24 -07004789static int in_get_active_microphones(const struct audio_stream_in *stream,
4790 struct audio_microphone_characteristic_t *mic_array,
4791 size_t *mic_count) {
4792 struct stream_in *in = (struct stream_in *)stream;
4793 struct audio_device *adev = in->dev;
4794 ALOGVV("%s", __func__);
4795
4796 lock_input_stream(in);
4797 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004798 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004799 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004800 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004801 pthread_mutex_unlock(&adev->lock);
4802 pthread_mutex_unlock(&in->lock);
4803
4804 return ret;
4805}
4806
4807static int adev_get_microphones(const struct audio_hw_device *dev,
4808 struct audio_microphone_characteristic_t *mic_array,
4809 size_t *mic_count) {
4810 struct audio_device *adev = (struct audio_device *)dev;
4811 ALOGVV("%s", __func__);
4812
4813 pthread_mutex_lock(&adev->lock);
4814 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4815 pthread_mutex_unlock(&adev->lock);
4816
4817 return ret;
4818}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004819
Paul McLean57530d52018-12-17 08:24:21 -07004820static int in_set_microphone_direction(const struct audio_stream_in *stream,
4821 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004822 struct stream_in *in = (struct stream_in *)stream;
4823
4824 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4825
4826 in->direction = dir;
4827
4828 if (in->standby)
4829 return 0;
4830
4831 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004832}
4833
4834static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004835 struct stream_in *in = (struct stream_in *)stream;
4836
4837 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4838
4839 if (zoom > 1.0 || zoom < -1.0)
4840 return -EINVAL;
4841
4842 in->zoom = zoom;
4843
4844 if (in->standby)
4845 return 0;
4846
4847 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004848}
4849
juyuchenba338cd2019-01-21 11:57:17 +08004850static void in_update_sink_metadata(struct audio_stream_in *stream,
4851 const struct sink_metadata *sink_metadata) {
4852
4853 if (stream == NULL
4854 || sink_metadata == NULL
4855 || sink_metadata->tracks == NULL) {
4856 return;
4857 }
4858
4859 int error = 0;
4860 struct stream_in *in = (struct stream_in *)stream;
4861 struct audio_device *adev = in->dev;
4862 audio_devices_t device = AUDIO_DEVICE_NONE;
4863
4864 if (sink_metadata->track_count != 0)
4865 device = sink_metadata->tracks->dest_device;
4866
4867 lock_input_stream(in);
4868 pthread_mutex_lock(&adev->lock);
4869 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4870
4871 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4872 && device != AUDIO_DEVICE_NONE
4873 && adev->voice_tx_output != NULL) {
4874 /* Use the rx device from afe-proxy record to route voice call because
4875 there is no routing if tx device is on primary hal and rx device
4876 is on other hal during voice call. */
4877 adev->voice_tx_output->devices = device;
4878
4879 if (!voice_is_call_state_active(adev)) {
4880 if (adev->mode == AUDIO_MODE_IN_CALL) {
4881 adev->current_call_output = adev->voice_tx_output;
4882 error = voice_start_call(adev);
4883 if (error != 0)
4884 ALOGE("%s: start voice call failed %d", __func__, error);
4885 }
4886 } else {
4887 adev->current_call_output = adev->voice_tx_output;
4888 voice_update_devices_for_all_voice_usecases(adev);
4889 }
4890 }
4891
4892 pthread_mutex_unlock(&adev->lock);
4893 pthread_mutex_unlock(&in->lock);
4894}
4895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896static int adev_open_output_stream(struct audio_hw_device *dev,
4897 audio_io_handle_t handle,
4898 audio_devices_t devices,
4899 audio_output_flags_t flags,
4900 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004901 struct audio_stream_out **stream_out,
4902 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903{
4904 struct audio_device *adev = (struct audio_device *)dev;
4905 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004906 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004907 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4908 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4909 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004910 bool force_haptic_path =
4911 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912
Andy Hungd9653bd2017-08-01 19:31:39 -07004913 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4914 return -ENOSYS;
4915 }
4916
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004917 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4918 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920 *stream_out = NULL;
4921 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4922
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004923 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925 if (devices == AUDIO_DEVICE_NONE)
4926 devices = AUDIO_DEVICE_OUT_SPEAKER;
4927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 out->flags = flags;
4929 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004930 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004931 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004932 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004933
4934 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004935 if ((is_hdmi || is_usb_dev) &&
4936 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4937 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4938 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004939 audio_format_t req_format = config->format;
4940 audio_channel_mask_t req_channel_mask = config->channel_mask;
4941 uint32_t req_sample_rate = config->sample_rate;
4942
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004943 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004944 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004945 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004946 if (config->sample_rate == 0)
4947 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004948 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004949 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4950 if (config->format == AUDIO_FORMAT_DEFAULT)
4951 config->format = AUDIO_FORMAT_PCM_16_BIT;
4952 } else if (is_usb_dev) {
4953 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4954 &config->format,
4955 &out->supported_formats[0],
4956 MAX_SUPPORTED_FORMATS,
4957 &config->channel_mask,
4958 &out->supported_channel_masks[0],
4959 MAX_SUPPORTED_CHANNEL_MASKS,
4960 &config->sample_rate,
4961 &out->supported_sample_rates[0],
4962 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004963 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004964 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004965 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004966 if (ret != 0) {
4967 // For MMAP NO IRQ, allow conversions in ADSP
4968 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4969 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004970
Eric Laurentab805ee2018-03-30 12:20:38 -07004971 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4972 config->sample_rate = req_sample_rate;
4973 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4974 config->channel_mask = req_channel_mask;
4975 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4976 config->format = req_format;
4977 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004978
Haynes Mathew George569b7482017-05-08 14:44:27 -07004979 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004980 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004981 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004982 if (is_hdmi) {
4983 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4984 out->config = pcm_config_hdmi_multi;
4985 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4986 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4987 out->config = pcm_config_mmap_playback;
4988 out->stream.start = out_start;
4989 out->stream.stop = out_stop;
4990 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4991 out->stream.get_mmap_position = out_get_mmap_position;
4992 } else {
4993 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4994 out->config = pcm_config_hifi;
4995 }
4996
4997 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004998 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004999 if (is_hdmi) {
5000 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
5001 audio_bytes_per_sample(out->format));
5002 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005003 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005004 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07005005 pthread_mutex_lock(&adev->lock);
5006 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
5007 pthread_mutex_unlock(&adev->lock);
5008
5009 // reject offload during card offline to allow
5010 // fallback to s/w paths
5011 if (offline) {
5012 ret = -ENODEV;
5013 goto error_open;
5014 }
5015
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005016 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
5017 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5018 ALOGE("%s: Unsupported Offload information", __func__);
5019 ret = -EINVAL;
5020 goto error_open;
5021 }
5022 if (!is_supported_format(config->offload_info.format)) {
5023 ALOGE("%s: Unsupported audio format", __func__);
5024 ret = -EINVAL;
5025 goto error_open;
5026 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005027 out->sample_rate = config->offload_info.sample_rate;
5028 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
5029 out->channel_mask = config->offload_info.channel_mask;
5030 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
5031 out->channel_mask = config->channel_mask;
5032 else
5033 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5034
5035 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005036
5037 out->compr_config.codec = (struct snd_codec *)
5038 calloc(1, sizeof(struct snd_codec));
5039
5040 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005041
5042 out->stream.set_callback = out_set_callback;
5043 out->stream.pause = out_pause;
5044 out->stream.resume = out_resume;
5045 out->stream.drain = out_drain;
5046 out->stream.flush = out_flush;
5047
5048 out->compr_config.codec->id =
5049 get_snd_codec_id(config->offload_info.format);
5050 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
5051 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005052 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005053 out->compr_config.codec->bit_rate =
5054 config->offload_info.bit_rate;
5055 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005056 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005057 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
5058
5059 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5060 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005061
5062 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005063 create_offload_callback_thread(out);
5064 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5065 __func__, config->offload_info.version,
5066 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02005067 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
5068 switch (config->sample_rate) {
5069 case 0:
5070 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5071 break;
5072 case 8000:
5073 case 16000:
5074 case 48000:
5075 out->sample_rate = config->sample_rate;
5076 break;
5077 default:
5078 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
5079 config->sample_rate);
5080 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5081 ret = -EINVAL;
5082 goto error_open;
5083 }
5084 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
5085 switch (config->channel_mask) {
5086 case AUDIO_CHANNEL_NONE:
5087 case AUDIO_CHANNEL_OUT_STEREO:
5088 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5089 break;
5090 default:
5091 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
5092 config->channel_mask);
5093 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5094 ret = -EINVAL;
5095 goto error_open;
5096 }
5097 switch (config->format) {
5098 case AUDIO_FORMAT_DEFAULT:
5099 case AUDIO_FORMAT_PCM_16_BIT:
5100 out->format = AUDIO_FORMAT_PCM_16_BIT;
5101 break;
5102 default:
5103 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
5104 config->format);
5105 config->format = AUDIO_FORMAT_PCM_16_BIT;
5106 ret = -EINVAL;
5107 goto error_open;
5108 }
5109
5110 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005111 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005112 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005113 case 0:
5114 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
5115 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07005116 case 8000:
5117 case 16000:
5118 case 48000:
5119 out->sample_rate = config->sample_rate;
5120 break;
5121 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005122 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
5123 config->sample_rate);
5124 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5125 ret = -EINVAL;
5126 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005127 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005128 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
5129 switch (config->channel_mask) {
5130 case AUDIO_CHANNEL_NONE:
5131 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5132 break;
5133 case AUDIO_CHANNEL_OUT_STEREO:
5134 out->channel_mask = config->channel_mask;
5135 break;
5136 default:
5137 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
5138 config->channel_mask);
5139 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5140 ret = -EINVAL;
5141 break;
5142 }
5143 switch (config->format) {
5144 case AUDIO_FORMAT_DEFAULT:
5145 out->format = AUDIO_FORMAT_PCM_16_BIT;
5146 break;
5147 case AUDIO_FORMAT_PCM_16_BIT:
5148 out->format = config->format;
5149 break;
5150 default:
5151 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
5152 config->format);
5153 config->format = AUDIO_FORMAT_PCM_16_BIT;
5154 ret = -EINVAL;
5155 break;
5156 }
5157 if (ret != 0)
5158 goto error_open;
5159
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005160 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5161 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005162 out->config.rate = out->sample_rate;
5163 out->config.channels =
5164 audio_channel_count_from_out_mask(out->channel_mask);
5165 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005166 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005167 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
5168 switch (config->sample_rate) {
5169 case 0:
5170 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5171 break;
5172 case 8000:
5173 case 16000:
5174 case 32000:
5175 case 48000:
5176 out->sample_rate = config->sample_rate;
5177 break;
5178 default:
5179 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
5180 config->sample_rate);
5181 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5182 ret = -EINVAL;
5183 break;
5184 }
Eric Laurentad2dde92017-09-20 18:27:31 -07005185 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005186 switch (config->channel_mask) {
5187 case AUDIO_CHANNEL_NONE:
5188 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5189 break;
5190 case AUDIO_CHANNEL_OUT_STEREO:
5191 out->channel_mask = config->channel_mask;
5192 break;
5193 default:
5194 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
5195 config->channel_mask);
5196 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5197 ret = -EINVAL;
5198 break;
5199 }
5200 switch (config->format) {
5201 case AUDIO_FORMAT_DEFAULT:
5202 out->format = AUDIO_FORMAT_PCM_16_BIT;
5203 break;
5204 case AUDIO_FORMAT_PCM_16_BIT:
5205 out->format = config->format;
5206 break;
5207 default:
5208 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5209 config->format);
5210 config->format = AUDIO_FORMAT_PCM_16_BIT;
5211 ret = -EINVAL;
5212 break;
5213 }
5214 if (ret != 0)
5215 goto error_open;
5216
vivek mehtaa68fea62017-06-08 19:04:02 -07005217 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005218 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5219 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005220 out->config.rate = out->sample_rate;
5221 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005222 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005223 out->sample_rate,
5224 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005225 out->config.channels,
5226 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005227 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005228 out->config.period_size = buffer_size / frame_size;
5229 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5230 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005232 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005233 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5234 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005235 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005236 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5237 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005238 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005239 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005240 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005241 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005242 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005243 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5244 out->config = pcm_config_mmap_playback;
5245 out->stream.start = out_start;
5246 out->stream.stop = out_stop;
5247 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5248 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005249 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005250 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5251 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5252 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5253 if (adev->haptic_pcm_device_id < 0) {
5254 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5255 __func__, adev->haptic_pcm_device_id, out->usecase);
5256 ret = -ENOSYS;
5257 goto error_open;
5258 }
5259 out->config = pcm_config_haptics_audio;
5260 if (force_haptic_path)
5261 adev->haptics_config = pcm_config_haptics_audio;
5262 else
5263 adev->haptics_config = pcm_config_haptics;
5264 } else {
5265 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5266 out->config = pcm_config_low_latency;
5267 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005268 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005269
5270 if (config->sample_rate == 0) {
5271 out->sample_rate = out->config.rate;
5272 } else {
5273 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005274 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005275
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005276 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5277 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5278 } else {
5279 out->channel_mask = config->channel_mask;
5280 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005281
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005282 if (config->format == AUDIO_FORMAT_DEFAULT)
5283 out->format = audio_format_from_pcm_format(out->config.format);
5284 else if (!audio_is_linear_pcm(config->format)) {
5285 config->format = AUDIO_FORMAT_PCM_16_BIT;
5286 ret = -EINVAL;
5287 goto error_open;
5288 } else {
5289 out->format = config->format;
5290 }
5291
5292 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005293
5294 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5295 out->config.channels =
5296 audio_channel_count_from_out_mask(out->channel_mask &
5297 ~AUDIO_CHANNEL_HAPTIC_ALL);
5298
5299 if (force_haptic_path) {
5300 out->config.channels = 1;
5301 adev->haptics_config.channels = 1;
5302 } else {
5303 adev->haptics_config.channels =
5304 audio_channel_count_from_out_mask(out->channel_mask &
5305 AUDIO_CHANNEL_HAPTIC_ALL);
5306 }
5307 } else {
5308 out->config.channels =
5309 audio_channel_count_from_out_mask(out->channel_mask);
5310 }
5311
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005312 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5313 out->config.format = pcm_format_from_audio_format(out->format);
5314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005316
5317 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5318 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005319 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005320 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5321 __func__, config->sample_rate, config->format, config->channel_mask);
5322 config->sample_rate = out->sample_rate;
5323 config->format = out->format;
5324 config->channel_mask = out->channel_mask;
5325 ret = -EINVAL;
5326 goto error_open;
5327 }
5328
Andy Hung6fcba9c2014-03-18 11:53:32 -07005329 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5330 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005332 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005333 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005334 adev->primary_output = out;
5335 else {
5336 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005337 ret = -EEXIST;
5338 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005339 }
5340 }
5341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005342 /* Check if this usecase is already existing */
5343 pthread_mutex_lock(&adev->lock);
5344 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5345 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005347 ret = -EEXIST;
5348 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005349 }
5350 pthread_mutex_unlock(&adev->lock);
5351
5352 out->stream.common.get_sample_rate = out_get_sample_rate;
5353 out->stream.common.set_sample_rate = out_set_sample_rate;
5354 out->stream.common.get_buffer_size = out_get_buffer_size;
5355 out->stream.common.get_channels = out_get_channels;
5356 out->stream.common.get_format = out_get_format;
5357 out->stream.common.set_format = out_set_format;
5358 out->stream.common.standby = out_standby;
5359 out->stream.common.dump = out_dump;
5360 out->stream.common.set_parameters = out_set_parameters;
5361 out->stream.common.get_parameters = out_get_parameters;
5362 out->stream.common.add_audio_effect = out_add_audio_effect;
5363 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5364 out->stream.get_latency = out_get_latency;
5365 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005366#ifdef NO_AUDIO_OUT
5367 out->stream.write = out_write_for_no_output;
5368#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005370#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371 out->stream.get_render_position = out_get_render_position;
5372 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005373 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374
Eric Laurent0e46adf2016-12-16 12:49:24 -08005375 if (out->realtime)
5376 out->af_period_multiplier = af_period_multiplier;
5377 else
5378 out->af_period_multiplier = 1;
5379
Andy Hung572633e2019-02-19 11:58:24 -08005380 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005382 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005383 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005384 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005385
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005386 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005387 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005388 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005390 config->format = out->stream.common.get_format(&out->stream.common);
5391 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5392 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5393
Kevin Rocarda325aa22018-04-03 09:15:52 -07005394 register_format(out->format, out->supported_formats);
5395 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5396 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5397
Andy Hunga452b0a2017-03-15 14:51:15 -07005398 out->error_log = error_log_create(
5399 ERROR_LOG_ENTRIES,
5400 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5401
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005402 /*
5403 By locking output stream before registering, we allow the callback
5404 to update stream's state only after stream's initial state is set to
5405 adev state.
5406 */
5407 lock_output_stream(out);
5408 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5409 pthread_mutex_lock(&adev->lock);
5410 out->card_status = adev->card_status;
5411 pthread_mutex_unlock(&adev->lock);
5412 pthread_mutex_unlock(&out->lock);
5413
vivek mehta4a824772017-06-08 19:05:49 -07005414 stream_app_type_cfg_init(&out->app_type_cfg);
5415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005416 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005417
Eric Laurent994a6932013-07-17 11:51:42 -07005418 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005420
5421error_open:
5422 free(out);
5423 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005424 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005425 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426}
5427
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005428static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005429 struct audio_stream_out *stream)
5430{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005431 struct stream_out *out = (struct stream_out *)stream;
5432 struct audio_device *adev = out->dev;
5433
Eric Laurent994a6932013-07-17 11:51:42 -07005434 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005435
5436 // must deregister from sndmonitor first to prevent races
5437 // between the callback and close_stream
5438 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005439 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005440 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5441 destroy_offload_callback_thread(out);
5442
5443 if (out->compr_config.codec != NULL)
5444 free(out->compr_config.codec);
5445 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005446
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005447 out->a2dp_compress_mute = false;
5448
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005449 if (adev->voice_tx_output == out)
5450 adev->voice_tx_output = NULL;
5451
Andy Hunga452b0a2017-03-15 14:51:15 -07005452 error_log_destroy(out->error_log);
5453 out->error_log = NULL;
5454
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005455 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005456 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005457 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005459 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460}
5461
5462static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5463{
5464 struct audio_device *adev = (struct audio_device *)dev;
5465 struct str_parms *parms;
5466 char *str;
5467 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005468 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005470 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005471 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005472
Joe Onorato188b6222016-03-01 11:02:27 -08005473 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005474
5475 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476
5477 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005478 status = voice_set_parameters(adev, parms);
5479 if (status != 0) {
5480 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005481 }
5482
5483 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5484 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005485 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005486 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5487 adev->bluetooth_nrec = true;
5488 else
5489 adev->bluetooth_nrec = false;
5490 }
5491
5492 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5493 if (ret >= 0) {
5494 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5495 adev->screen_off = false;
5496 else
5497 adev->screen_off = true;
5498 }
5499
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005500 ret = str_parms_get_int(parms, "rotation", &val);
5501 if (ret >= 0) {
5502 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005503 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005504 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005505 // FIXME: note that the code below assumes that the speakers are in the correct placement
5506 // relative to the user when the device is rotated 90deg from its default rotation. This
5507 // assumption is device-specific, not platform-specific like this code.
5508 case 270:
5509 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005510 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005511 break;
5512 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005513 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005514 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5515 break;
5516 case 90:
5517 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005518 break;
5519 default:
5520 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005521 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005522 }
Eric Laurent03f09432014-03-25 18:09:11 -07005523 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005524 // check and set swap
5525 // - check if orientation changed and speaker active
5526 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005527 adev->camera_orientation =
5528 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5529#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005530 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005531#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005532 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005533 }
5534
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005535 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5536 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005537 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005538 }
5539
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07005540 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5541 if (ret >= 0) {
5542 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5543 adev->bt_sco_on = true;
5544 else
5545 adev->bt_sco_on = false;
5546 }
5547
David Linee3fe402017-03-13 10:00:42 -07005548 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5549 if (ret >= 0) {
5550 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005551 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005552 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5553 if (ret >= 0) {
5554 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005555 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005556 }
Eric Laurent99dab492017-06-17 15:19:08 -07005557 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005558 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5559 if (ret >= 0) {
5560 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005561 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005562 }
5563 }
5564 }
5565
5566 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5567 if (ret >= 0) {
5568 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005569 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005570 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5571 if (ret >= 0) {
5572 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005573 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005574 }
Eric Laurent99dab492017-06-17 15:19:08 -07005575 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005576 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5577 if (ret >= 0) {
5578 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005579 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005580 }
5581 }
5582 }
5583
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005584 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005585 audio_extn_ma_set_parameters(adev, parms);
5586
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005587 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5588 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005589 struct audio_usecase *usecase;
5590 struct listnode *node;
5591 list_for_each(node, &adev->usecase_list) {
5592 usecase = node_to_item(node, struct audio_usecase, list);
5593 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005594 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005595 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5596
5597 pthread_mutex_unlock(&adev->lock);
5598 lock_output_stream(usecase->stream.out);
5599 pthread_mutex_lock(&adev->lock);
5600 audio_extn_a2dp_set_handoff_mode(true);
5601 // force device switch to reconfigure encoder
5602 select_devices(adev, usecase->id);
5603 audio_extn_a2dp_set_handoff_mode(false);
5604 pthread_mutex_unlock(&usecase->stream.out->lock);
5605 break;
5606 }
5607 }
5608 }
5609
Eric Laurent5f4ca952018-10-19 17:33:43 -07005610 //FIXME: to be replaced by proper video capture properties API
5611 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5612 if (ret >= 0) {
5613 int camera_facing = CAMERA_FACING_BACK;
5614 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5615 camera_facing = CAMERA_FACING_FRONT;
5616 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5617 camera_facing = CAMERA_FACING_BACK;
5618 else {
5619 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5620 goto done;
5621 }
5622 adev->camera_orientation =
5623 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5624 struct audio_usecase *usecase;
5625 struct listnode *node;
5626 list_for_each(node, &adev->usecase_list) {
5627 usecase = node_to_item(node, struct audio_usecase, list);
5628 struct stream_in *in = usecase->stream.in;
5629 if (usecase->type == PCM_CAPTURE && in != NULL &&
5630 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5631 select_devices(adev, in->usecase);
5632 }
5633 }
5634 }
5635
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005636done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005637 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005638 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005639 ALOGV("%s: exit with code(%d)", __func__, status);
5640 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005641}
5642
5643static char* adev_get_parameters(const struct audio_hw_device *dev,
5644 const char *keys)
5645{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005646 struct audio_device *adev = (struct audio_device *)dev;
5647 struct str_parms *reply = str_parms_create();
5648 struct str_parms *query = str_parms_create_str(keys);
5649 char *str;
5650
5651 pthread_mutex_lock(&adev->lock);
5652
5653 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005654 audio_extn_a2dp_get_parameters(query, reply);
5655
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005656 str = str_parms_to_str(reply);
5657 str_parms_destroy(query);
5658 str_parms_destroy(reply);
5659
5660 pthread_mutex_unlock(&adev->lock);
5661 ALOGV("%s: exit: returns - %s", __func__, str);
5662 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005663}
5664
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005665static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005666{
5667 return 0;
5668}
5669
Haynes Mathew George5191a852013-09-11 14:19:36 -07005670static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5671{
5672 int ret;
5673 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005674
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005675 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5676
Haynes Mathew George5191a852013-09-11 14:19:36 -07005677 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005678 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005679 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005680
Haynes Mathew George5191a852013-09-11 14:19:36 -07005681 return ret;
5682}
5683
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005684static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005685{
5686 return -ENOSYS;
5687}
5688
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005689static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5690 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691{
5692 return -ENOSYS;
5693}
5694
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005695static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696{
5697 return -ENOSYS;
5698}
5699
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005700static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701{
5702 return -ENOSYS;
5703}
5704
5705static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5706{
5707 struct audio_device *adev = (struct audio_device *)dev;
5708
5709 pthread_mutex_lock(&adev->lock);
5710 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005711 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005712 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005713 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5714 voice_is_in_call(adev)) {
5715 voice_stop_call(adev);
5716 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005717
5718 /*
5719 * After stopping the call, it must check if any active capture
5720 * activity device needs to be re-selected.
5721 */
5722 struct audio_usecase *usecase;
5723 struct listnode *node;
5724 list_for_each(node, &adev->usecase_list) {
5725 usecase = node_to_item(node, struct audio_usecase, list);
5726 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5727 select_devices_with_force_switch(adev, usecase->id, true);
5728 }
5729 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005730 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005731 }
5732 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005733
5734 audio_extn_extspk_set_mode(adev->extspk, mode);
5735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005736 return 0;
5737}
5738
5739static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5740{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005741 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005742 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743
Eric Laurent2bafff12016-03-17 12:17:23 -07005744 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005745 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005746 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5747 ret = audio_extn_hfp_set_mic_mute(adev, state);
5748 } else {
5749 ret = voice_set_mic_mute(adev, state);
5750 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005751 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005752 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005753
5754 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005755}
5756
5757static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5758{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005759 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005760 return 0;
5761}
5762
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005763static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005764 const struct audio_config *config)
5765{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005766 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005767
Eric Laurent74b55762017-07-09 17:04:53 -07005768 /* Don't know if USB HIFI in this context so use true to be conservative */
5769 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5770 true /*is_usb_hifi */) != 0)
5771 return 0;
5772
vivek mehtaa68fea62017-06-08 19:04:02 -07005773 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5774 config->sample_rate, config->format,
5775 channel_count,
5776 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005777}
5778
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005779static bool adev_input_allow_hifi_record(struct audio_device *adev,
5780 audio_devices_t devices,
5781 audio_input_flags_t flags,
5782 audio_source_t source) {
5783 const bool allowed = true;
5784
5785 if (!audio_is_usb_in_device(devices))
5786 return !allowed;
5787
5788 switch (flags) {
5789 case AUDIO_INPUT_FLAG_NONE:
5790 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5791 break;
5792 default:
5793 return !allowed;
5794 }
5795
5796 switch (source) {
5797 case AUDIO_SOURCE_DEFAULT:
5798 case AUDIO_SOURCE_MIC:
5799 case AUDIO_SOURCE_UNPROCESSED:
5800 break;
5801 default:
5802 return !allowed;
5803 }
5804
5805 switch (adev->mode) {
5806 case 0:
5807 break;
5808 default:
5809 return !allowed;
5810 }
5811
5812 return allowed;
5813}
5814
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005815static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005816 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005817 audio_devices_t devices,
5818 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005819 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005820 audio_input_flags_t flags,
5821 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005822 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005823{
5824 struct audio_device *adev = (struct audio_device *)dev;
5825 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005826 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005827 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005828 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005829 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005830 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5831 devices,
5832 flags,
5833 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005834 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5835 " sample_rate %u, channel_mask %#x, format %#x",
5836 __func__, flags, is_usb_dev, may_use_hifi_record,
5837 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005838 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005839
Andy Hungd9653bd2017-08-01 19:31:39 -07005840 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5841 return -ENOSYS;
5842 }
5843
Eric Laurent74b55762017-07-09 17:04:53 -07005844 if (!(is_usb_dev && may_use_hifi_record)) {
5845 if (config->sample_rate == 0)
5846 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5847 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5848 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5849 if (config->format == AUDIO_FORMAT_DEFAULT)
5850 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005851
Eric Laurent74b55762017-07-09 17:04:53 -07005852 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5853
5854 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5855 return -EINVAL;
5856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005857
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005858 if (audio_extn_tfa_98xx_is_supported() &&
5859 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005860 return -EINVAL;
5861
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005862 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5863
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005864 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005865 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005867 in->stream.common.get_sample_rate = in_get_sample_rate;
5868 in->stream.common.set_sample_rate = in_set_sample_rate;
5869 in->stream.common.get_buffer_size = in_get_buffer_size;
5870 in->stream.common.get_channels = in_get_channels;
5871 in->stream.common.get_format = in_get_format;
5872 in->stream.common.set_format = in_set_format;
5873 in->stream.common.standby = in_standby;
5874 in->stream.common.dump = in_dump;
5875 in->stream.common.set_parameters = in_set_parameters;
5876 in->stream.common.get_parameters = in_get_parameters;
5877 in->stream.common.add_audio_effect = in_add_audio_effect;
5878 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5879 in->stream.set_gain = in_set_gain;
5880 in->stream.read = in_read;
5881 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005882 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005883 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005884 in->stream.set_microphone_direction = in_set_microphone_direction;
5885 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005886 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005887
5888 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005889 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005891 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005892 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005893 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005894 in->direction = MIC_DIRECTION_UNSPECIFIED;
5895 in->zoom = 0;
Carter Hsub0c91482019-05-14 18:50:52 +08005896 list_init(&in->aec_list);
5897 list_init(&in->ns_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005898
Andy Hung88ce1d92018-10-29 18:31:12 -07005899 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005900 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5901 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5902 /* Force channel config requested to mono if incall
5903 record is being requested for only uplink/downlink */
5904 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5905 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5906 ret = -EINVAL;
5907 goto err_open;
5908 }
5909 }
5910
Haynes Mathew George569b7482017-05-08 14:44:27 -07005911 if (is_usb_dev && may_use_hifi_record) {
5912 /* HiFi record selects an appropriate format, channel, rate combo
5913 depending on sink capabilities*/
5914 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5915 &config->format,
5916 &in->supported_formats[0],
5917 MAX_SUPPORTED_FORMATS,
5918 &config->channel_mask,
5919 &in->supported_channel_masks[0],
5920 MAX_SUPPORTED_CHANNEL_MASKS,
5921 &config->sample_rate,
5922 &in->supported_sample_rates[0],
5923 MAX_SUPPORTED_SAMPLE_RATES);
5924 if (ret != 0) {
5925 ret = -EINVAL;
5926 goto err_open;
5927 }
Eric Laurent74b55762017-07-09 17:04:53 -07005928 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005929 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005930 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005931 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5932 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5933 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5934 bool ret_error = false;
5935 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5936 from HAL is 8_24
5937 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5938 8_24 return error indicating supported format is 8_24
5939 *> In case of any other source requesting 24 bit or float return error
5940 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005941
vivek mehta57ff9b52016-04-28 14:13:08 -07005942 on error flinger will retry with supported format passed
5943 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005944 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005945 config->format = AUDIO_FORMAT_PCM_16_BIT;
5946 ret_error = true;
5947 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5948 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5949 ret_error = true;
5950 }
5951
5952 if (ret_error) {
5953 ret = -EINVAL;
5954 goto err_open;
5955 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005956 }
5957
vivek mehta57ff9b52016-04-28 14:13:08 -07005958 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005959 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005961 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005962 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5963 if (config->sample_rate == 0)
5964 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5965 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5966 config->sample_rate != 8000) {
5967 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5968 ret = -EINVAL;
5969 goto err_open;
5970 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005971
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005972 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5973 config->format = AUDIO_FORMAT_PCM_16_BIT;
5974 ret = -EINVAL;
5975 goto err_open;
5976 }
5977
5978 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5979 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005980 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005981 } else if (is_usb_dev && may_use_hifi_record) {
5982 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5983 in->config = pcm_config_audio_capture;
5984 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005985 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5986 config->sample_rate,
5987 config->format,
5988 channel_count,
5989 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005990 in->config.period_size = buffer_size / frame_size;
5991 in->config.rate = config->sample_rate;
5992 in->af_period_multiplier = 1;
5993 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005994 } else {
5995 in->usecase = USECASE_AUDIO_RECORD;
5996 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005997 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005998 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005999#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07006000 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07006001#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08006002 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08006003 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08006004 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006005 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07006006 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
6007 config->sample_rate,
6008 config->format,
6009 channel_count,
6010 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08006011 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006012 in->config.rate = config->sample_rate;
6013 in->af_period_multiplier = 1;
6014 } else {
6015 // period size is left untouched for rt mode playback
6016 in->config = pcm_config_audio_capture_rt;
6017 in->af_period_multiplier = af_period_multiplier;
6018 }
6019 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6020 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07006021 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08006022 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6023 in->config = pcm_config_mmap_capture;
6024 in->stream.start = in_start;
6025 in->stream.stop = in_stop;
6026 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6027 in->stream.get_mmap_position = in_get_mmap_position;
6028 in->af_period_multiplier = 1;
6029 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07006030 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07006031 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07006032 (config->sample_rate == 8000 ||
6033 config->sample_rate == 16000 ||
6034 config->sample_rate == 32000 ||
6035 config->sample_rate == 48000) &&
6036 channel_count == 1) {
6037 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6038 in->config = pcm_config_audio_capture;
6039 frame_size = audio_stream_in_frame_size(&in->stream);
6040 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
6041 config->sample_rate,
6042 config->format,
6043 channel_count, false /*is_low_latency*/);
6044 in->config.period_size = buffer_size / frame_size;
6045 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
6046 in->config.rate = config->sample_rate;
6047 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006048 } else {
6049 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006050 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07006051 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
6052 config->sample_rate,
6053 config->format,
6054 channel_count,
6055 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08006056 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006057 in->config.rate = config->sample_rate;
6058 in->af_period_multiplier = 1;
6059 }
6060 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
6061 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07006062 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08006063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006064 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07006065 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066
Kevin Rocarda325aa22018-04-03 09:15:52 -07006067
6068 register_format(in->format, in->supported_formats);
6069 register_channel_mask(in->channel_mask, in->supported_channel_masks);
6070 register_sample_rate(in->sample_rate, in->supported_sample_rates);
6071
Andy Hungd13f0d32017-06-12 13:58:37 -07006072 in->error_log = error_log_create(
6073 ERROR_LOG_ENTRIES,
6074 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
6075
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07006076 /* This stream could be for sound trigger lab,
6077 get sound trigger pcm if present */
6078 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006079
Carter Hsu968d6812019-06-12 21:36:14 +08006080 if (in->is_st_session)
6081 in->flags |= AUDIO_INPUT_FLAG_HW_HOTWORD;
6082
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006083 lock_input_stream(in);
6084 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6085 pthread_mutex_lock(&adev->lock);
6086 in->card_status = adev->card_status;
6087 pthread_mutex_unlock(&adev->lock);
6088 pthread_mutex_unlock(&in->lock);
6089
vivek mehta4a824772017-06-08 19:05:49 -07006090 stream_app_type_cfg_init(&in->app_type_cfg);
6091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006092 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006093 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006094 return 0;
6095
6096err_open:
6097 free(in);
6098 *stream_in = NULL;
6099 return ret;
6100}
6101
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07006102static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006103 struct audio_stream_in *stream)
6104{
Andy Hungd13f0d32017-06-12 13:58:37 -07006105 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006106 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006107
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006108 // must deregister from sndmonitor first to prevent races
6109 // between the callback and close_stream
6110 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006111 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07006112
6113 error_log_destroy(in->error_log);
6114 in->error_log = NULL;
6115
Andy Hung0dbb52b2017-08-09 13:51:38 -07006116 pthread_mutex_destroy(&in->pre_lock);
6117 pthread_mutex_destroy(&in->lock);
6118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006119 free(stream);
6120
6121 return;
6122}
6123
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07006124static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006125{
6126 return 0;
6127}
6128
Andy Hung31aca912014-03-20 17:14:59 -07006129/* verifies input and output devices and their capabilities.
6130 *
6131 * This verification is required when enabling extended bit-depth or
6132 * sampling rates, as not all qcom products support it.
6133 *
6134 * Suitable for calling only on initialization such as adev_open().
6135 * It fills the audio_device use_case_table[] array.
6136 *
6137 * Has a side-effect that it needs to configure audio routing / devices
6138 * in order to power up the devices and read the device parameters.
6139 * It does not acquire any hw device lock. Should restore the devices
6140 * back to "normal state" upon completion.
6141 */
6142static int adev_verify_devices(struct audio_device *adev)
6143{
6144 /* enumeration is a bit difficult because one really wants to pull
6145 * the use_case, device id, etc from the hidden pcm_device_table[].
6146 * In this case there are the following use cases and device ids.
6147 *
6148 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
6149 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006150 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07006151 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
6152 * [USECASE_AUDIO_RECORD] = {0, 0},
6153 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
6154 * [USECASE_VOICE_CALL] = {2, 2},
6155 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006156 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07006157 * USECASE_VOICE_CALL omitted, but possible for either input or output.
6158 */
6159
6160 /* should be the usecases enabled in adev_open_input_stream() */
6161 static const int test_in_usecases[] = {
6162 USECASE_AUDIO_RECORD,
6163 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
6164 };
6165 /* should be the usecases enabled in adev_open_output_stream()*/
6166 static const int test_out_usecases[] = {
6167 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
6168 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
6169 };
6170 static const usecase_type_t usecase_type_by_dir[] = {
6171 PCM_PLAYBACK,
6172 PCM_CAPTURE,
6173 };
6174 static const unsigned flags_by_dir[] = {
6175 PCM_OUT,
6176 PCM_IN,
6177 };
6178
6179 size_t i;
6180 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006181 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07006182 char info[512]; /* for possible debug info */
6183
6184 for (dir = 0; dir < 2; ++dir) {
6185 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
6186 const unsigned flags_dir = flags_by_dir[dir];
6187 const size_t testsize =
6188 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
6189 const int *testcases =
6190 dir ? test_in_usecases : test_out_usecases;
6191 const audio_devices_t audio_device =
6192 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
6193
6194 for (i = 0; i < testsize; ++i) {
6195 const audio_usecase_t audio_usecase = testcases[i];
6196 int device_id;
6197 snd_device_t snd_device;
6198 struct pcm_params **pparams;
6199 struct stream_out out;
6200 struct stream_in in;
6201 struct audio_usecase uc_info;
6202 int retval;
6203
6204 pparams = &adev->use_case_table[audio_usecase];
6205 pcm_params_free(*pparams); /* can accept null input */
6206 *pparams = NULL;
6207
6208 /* find the device ID for the use case (signed, for error) */
6209 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
6210 if (device_id < 0)
6211 continue;
6212
6213 /* prepare structures for device probing */
6214 memset(&uc_info, 0, sizeof(uc_info));
6215 uc_info.id = audio_usecase;
6216 uc_info.type = usecase_type;
6217 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07006218 memset(&in, 0, sizeof(in));
6219 in.device = audio_device;
6220 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
6221 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07006222 }
6223 memset(&out, 0, sizeof(out));
6224 out.devices = audio_device; /* only field needed in select_devices */
6225 uc_info.stream.out = &out;
6226 uc_info.devices = audio_device;
6227 uc_info.in_snd_device = SND_DEVICE_NONE;
6228 uc_info.out_snd_device = SND_DEVICE_NONE;
6229 list_add_tail(&adev->usecase_list, &uc_info.list);
6230
6231 /* select device - similar to start_(in/out)put_stream() */
6232 retval = select_devices(adev, audio_usecase);
6233 if (retval >= 0) {
6234 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6235#if LOG_NDEBUG == 0
6236 if (*pparams) {
6237 ALOGV("%s: (%s) card %d device %d", __func__,
6238 dir ? "input" : "output", card_id, device_id);
6239 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006240 } else {
6241 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6242 }
6243#endif
6244 }
6245
6246 /* deselect device - similar to stop_(in/out)put_stream() */
6247 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006248 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006249 /* 2. Disable the rx device */
6250 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006251 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006252 list_remove(&uc_info.list);
6253 }
6254 }
Andy Hung31aca912014-03-20 17:14:59 -07006255 return 0;
6256}
6257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006258static int adev_close(hw_device_t *device)
6259{
Andy Hung31aca912014-03-20 17:14:59 -07006260 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006262
6263 if (!adev)
6264 return 0;
6265
6266 pthread_mutex_lock(&adev_init_lock);
6267
6268 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006269 audio_extn_snd_mon_unregister_listener(adev);
6270 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006271 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006272 audio_route_free(adev->audio_route);
6273 free(adev->snd_dev_ref_cnt);
6274 platform_deinit(adev->platform);
6275 audio_extn_extspk_deinit(adev->extspk);
6276 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006277 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006278 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6279 pcm_params_free(adev->use_case_table[i]);
6280 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006281 if (adev->adm_deinit)
6282 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006283 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006284 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006285 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006286
6287 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006288
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006289 return 0;
6290}
6291
Glenn Kasten4f993392014-05-14 07:30:48 -07006292/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6293 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6294 * just that it _might_ work.
6295 */
6296static int period_size_is_plausible_for_low_latency(int period_size)
6297{
6298 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006299 case 48:
6300 case 96:
6301 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006302 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006303 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006304 case 240:
6305 case 320:
6306 case 480:
6307 return 1;
6308 default:
6309 return 0;
6310 }
6311}
6312
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006313static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6314{
6315 int card;
6316 card_status_t status;
6317
6318 if (!parms)
6319 return;
6320
6321 if (parse_snd_card_status(parms, &card, &status) < 0)
6322 return;
6323
6324 pthread_mutex_lock(&adev->lock);
6325 bool valid_cb = (card == adev->snd_card);
6326 if (valid_cb) {
6327 if (adev->card_status != status) {
6328 adev->card_status = status;
6329 platform_snd_card_update(adev->platform, status);
6330 }
6331 }
6332 pthread_mutex_unlock(&adev->lock);
6333 return;
6334}
6335
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006336/* out and adev lock held */
6337static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6338{
6339 struct audio_usecase *uc_info;
6340 float left_p;
6341 float right_p;
6342 audio_devices_t devices;
6343
6344 uc_info = get_usecase_from_list(adev, out->usecase);
6345 if (uc_info == NULL) {
6346 ALOGE("%s: Could not find the usecase (%d) in the list",
6347 __func__, out->usecase);
6348 return -EINVAL;
6349 }
6350
6351 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6352 out->usecase, use_case_table[out->usecase]);
6353
6354 if (restore) {
6355 // restore A2DP device for active usecases and unmute if required
6356 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6357 !is_a2dp_device(uc_info->out_snd_device)) {
6358 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6359 select_devices(adev, uc_info->id);
6360 pthread_mutex_lock(&out->compr_mute_lock);
6361 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6362 (out->a2dp_compress_mute)) {
6363 out->a2dp_compress_mute = false;
6364 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6365 }
6366 pthread_mutex_unlock(&out->compr_mute_lock);
6367 }
6368 } else {
6369 // mute compress stream if suspended
6370 pthread_mutex_lock(&out->compr_mute_lock);
6371 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6372 (!out->a2dp_compress_mute)) {
6373 if (!out->standby) {
6374 ALOGD("%s: selecting speaker and muting stream", __func__);
6375 devices = out->devices;
6376 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6377 left_p = out->volume_l;
6378 right_p = out->volume_r;
6379 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6380 compress_pause(out->compr);
6381 set_compr_volume(&out->stream, 0.0f, 0.0f);
6382 out->a2dp_compress_mute = true;
6383 select_devices(adev, out->usecase);
6384 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6385 compress_resume(out->compr);
6386 out->devices = devices;
6387 out->volume_l = left_p;
6388 out->volume_r = right_p;
6389 }
6390 }
6391 pthread_mutex_unlock(&out->compr_mute_lock);
6392 }
6393 ALOGV("%s: exit", __func__);
6394 return 0;
6395}
6396
6397int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6398{
6399 int ret = 0;
6400
6401 lock_output_stream(out);
6402 pthread_mutex_lock(&adev->lock);
6403
6404 ret = check_a2dp_restore_l(adev, out, restore);
6405
6406 pthread_mutex_unlock(&adev->lock);
6407 pthread_mutex_unlock(&out->lock);
6408 return ret;
6409}
6410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006411static int adev_open(const hw_module_t *module, const char *name,
6412 hw_device_t **device)
6413{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006414 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415
Eric Laurent2bafff12016-03-17 12:17:23 -07006416 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006417 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006418 pthread_mutex_lock(&adev_init_lock);
6419 if (audio_device_ref_count != 0) {
6420 *device = &adev->device.common;
6421 audio_device_ref_count++;
6422 ALOGV("%s: returning existing instance of adev", __func__);
6423 ALOGV("%s: exit", __func__);
6424 pthread_mutex_unlock(&adev_init_lock);
6425 return 0;
6426 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006427 adev = calloc(1, sizeof(struct audio_device));
6428
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006429 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006431 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6432 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6433 adev->device.common.module = (struct hw_module_t *)module;
6434 adev->device.common.close = adev_close;
6435
6436 adev->device.init_check = adev_init_check;
6437 adev->device.set_voice_volume = adev_set_voice_volume;
6438 adev->device.set_master_volume = adev_set_master_volume;
6439 adev->device.get_master_volume = adev_get_master_volume;
6440 adev->device.set_master_mute = adev_set_master_mute;
6441 adev->device.get_master_mute = adev_get_master_mute;
6442 adev->device.set_mode = adev_set_mode;
6443 adev->device.set_mic_mute = adev_set_mic_mute;
6444 adev->device.get_mic_mute = adev_get_mic_mute;
6445 adev->device.set_parameters = adev_set_parameters;
6446 adev->device.get_parameters = adev_get_parameters;
6447 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6448 adev->device.open_output_stream = adev_open_output_stream;
6449 adev->device.close_output_stream = adev_close_output_stream;
6450 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 adev->device.close_input_stream = adev_close_input_stream;
6453 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006454 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006455
6456 /* Set the default route before the PCM stream is opened */
6457 pthread_mutex_lock(&adev->lock);
6458 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006459 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006460 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006461 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006462 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006463 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006464 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006465 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006466 pthread_mutex_unlock(&adev->lock);
6467
6468 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006469 adev->platform = platform_init(adev);
6470 if (!adev->platform) {
6471 free(adev->snd_dev_ref_cnt);
6472 free(adev);
6473 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6474 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006475 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006476 return -EINVAL;
6477 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006478 adev->extspk = audio_extn_extspk_init(adev);
6479
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006480 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6481 if (adev->visualizer_lib == NULL) {
6482 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6483 } else {
6484 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6485 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006486 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006487 "visualizer_hal_start_output");
6488 adev->visualizer_stop_output =
6489 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6490 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006491 }
6492
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006493 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6494 if (adev->offload_effects_lib == NULL) {
6495 ALOGW("%s: DLOPEN failed for %s", __func__,
6496 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6497 } else {
6498 ALOGV("%s: DLOPEN successful for %s", __func__,
6499 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6500 adev->offload_effects_start_output =
6501 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6502 "offload_effects_bundle_hal_start_output");
6503 adev->offload_effects_stop_output =
6504 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6505 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006506 }
6507
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006508 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6509 if (adev->adm_lib == NULL) {
6510 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6511 } else {
6512 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6513 adev->adm_init = (adm_init_t)
6514 dlsym(adev->adm_lib, "adm_init");
6515 adev->adm_deinit = (adm_deinit_t)
6516 dlsym(adev->adm_lib, "adm_deinit");
6517 adev->adm_register_input_stream = (adm_register_input_stream_t)
6518 dlsym(adev->adm_lib, "adm_register_input_stream");
6519 adev->adm_register_output_stream = (adm_register_output_stream_t)
6520 dlsym(adev->adm_lib, "adm_register_output_stream");
6521 adev->adm_deregister_stream = (adm_deregister_stream_t)
6522 dlsym(adev->adm_lib, "adm_deregister_stream");
6523 adev->adm_request_focus = (adm_request_focus_t)
6524 dlsym(adev->adm_lib, "adm_request_focus");
6525 adev->adm_abandon_focus = (adm_abandon_focus_t)
6526 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006527 adev->adm_set_config = (adm_set_config_t)
6528 dlsym(adev->adm_lib, "adm_set_config");
6529 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6530 dlsym(adev->adm_lib, "adm_request_focus_v2");
6531 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6532 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6533 adev->adm_on_routing_change = (adm_on_routing_change_t)
6534 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006535 }
6536
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006537 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006538 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006540 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006541
Andy Hung31aca912014-03-20 17:14:59 -07006542 if (k_enable_extended_precision)
6543 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006544
Glenn Kasten4f993392014-05-14 07:30:48 -07006545 char value[PROPERTY_VALUE_MAX];
6546 int trial;
6547 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6548 trial = atoi(value);
6549 if (period_size_is_plausible_for_low_latency(trial)) {
6550 pcm_config_low_latency.period_size = trial;
6551 pcm_config_low_latency.start_threshold = trial / 4;
6552 pcm_config_low_latency.avail_min = trial / 4;
6553 configured_low_latency_capture_period_size = trial;
6554 }
6555 }
6556 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6557 trial = atoi(value);
6558 if (period_size_is_plausible_for_low_latency(trial)) {
6559 configured_low_latency_capture_period_size = trial;
6560 }
6561 }
6562
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006563 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6564
Eric Laurent5f4ca952018-10-19 17:33:43 -07006565 adev->camera_orientation = CAMERA_DEFAULT;
6566
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006567 // commented as full set of app type cfg is sent from platform
6568 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006569 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006570
6571 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6572 af_period_multiplier = atoi(value);
6573 if (af_period_multiplier < 0) {
6574 af_period_multiplier = 2;
6575 } else if (af_period_multiplier > 4) {
6576 af_period_multiplier = 4;
6577 }
6578 ALOGV("new period_multiplier = %d", af_period_multiplier);
6579 }
6580
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006581 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006582 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006583 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006584
vivek mehta1a9b7c02015-06-25 11:49:38 -07006585 pthread_mutex_unlock(&adev_init_lock);
6586
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006587 if (adev->adm_init)
6588 adev->adm_data = adev->adm_init();
6589
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006590 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006591 audio_extn_snd_mon_init();
6592 pthread_mutex_lock(&adev->lock);
6593 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6594 adev->card_status = CARD_STATUS_ONLINE;
6595 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006596 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006597
Eric Laurent2bafff12016-03-17 12:17:23 -07006598 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599 return 0;
6600}
6601
6602static struct hw_module_methods_t hal_module_methods = {
6603 .open = adev_open,
6604};
6605
6606struct audio_module HAL_MODULE_INFO_SYM = {
6607 .common = {
6608 .tag = HARDWARE_MODULE_TAG,
6609 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6610 .hal_api_version = HARDWARE_HAL_API_VERSION,
6611 .id = AUDIO_HARDWARE_MODULE_ID,
6612 .name = "QCOM Audio HAL",
6613 .author = "Code Aurora Forum",
6614 .methods = &hal_module_methods,
6615 },
6616};