blob: 2113c7db500b202586df8b7c9583b9e49daf3b8c [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",
Aniket Kumar Lata99546312018-03-19 21:38:38 -0700318
319 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700320};
321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800322
323#define STRING_TO_ENUM(string) { #string, string }
324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800325struct string_to_enum {
326 const char *name;
327 uint32_t value;
328};
329
Haynes Mathew George569b7482017-05-08 14:44:27 -0700330static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800331 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
332 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
333 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700334 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700335 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700336 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
337 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
338 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
339 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
340 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
341 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
342 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
343 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
344 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800345};
346
Carter Hsub0c91482019-05-14 18:50:52 +0800347struct in_effect_list {
348 struct listnode list;
349 effect_handle_t handle;
350};
351
Haynes Mathew George5191a852013-09-11 14:19:36 -0700352static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700353static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700354static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700355static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700356//cache last MBDRC cal step level
357static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700358
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800359static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
360static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
361
justinwengc6347db2019-02-21 18:49:00 +0800362static int in_set_microphone_direction(const struct audio_stream_in *stream,
363 audio_microphone_direction_t dir);
364static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
365
Haynes Mathew George03c40102016-01-29 17:57:48 -0800366static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
367 int flags __unused)
368{
369 int dir = 0;
370 switch (uc_id) {
371 case USECASE_AUDIO_RECORD_LOW_LATENCY:
372 dir = 1;
373 case USECASE_AUDIO_PLAYBACK_ULL:
374 break;
375 default:
376 return false;
377 }
378
379 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
380 PCM_PLAYBACK : PCM_CAPTURE);
381 if (adev->adm_is_noirq_avail)
382 return adev->adm_is_noirq_avail(adev->adm_data,
383 adev->snd_card, dev_id, dir);
384 return false;
385}
386
387static void register_out_stream(struct stream_out *out)
388{
389 struct audio_device *adev = out->dev;
390 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
391 return;
392
393 if (!adev->adm_register_output_stream)
394 return;
395
396 adev->adm_register_output_stream(adev->adm_data,
397 out->handle,
398 out->flags);
399
400 if (!adev->adm_set_config)
401 return;
402
403 if (out->realtime) {
404 adev->adm_set_config(adev->adm_data,
405 out->handle,
406 out->pcm, &out->config);
407 }
408}
409
410static void register_in_stream(struct stream_in *in)
411{
412 struct audio_device *adev = in->dev;
413 if (!adev->adm_register_input_stream)
414 return;
415
416 adev->adm_register_input_stream(adev->adm_data,
417 in->capture_handle,
418 in->flags);
419
420 if (!adev->adm_set_config)
421 return;
422
423 if (in->realtime) {
424 adev->adm_set_config(adev->adm_data,
425 in->capture_handle,
426 in->pcm,
427 &in->config);
428 }
429}
430
431static void request_out_focus(struct stream_out *out, long ns)
432{
433 struct audio_device *adev = out->dev;
434
Haynes Mathew George03c40102016-01-29 17:57:48 -0800435 if (adev->adm_request_focus_v2) {
436 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
437 } else if (adev->adm_request_focus) {
438 adev->adm_request_focus(adev->adm_data, out->handle);
439 }
440}
441
442static void request_in_focus(struct stream_in *in, long ns)
443{
444 struct audio_device *adev = in->dev;
445
Haynes Mathew George03c40102016-01-29 17:57:48 -0800446 if (adev->adm_request_focus_v2) {
447 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
448 } else if (adev->adm_request_focus) {
449 adev->adm_request_focus(adev->adm_data, in->capture_handle);
450 }
451}
452
453static void release_out_focus(struct stream_out *out, long ns __unused)
454{
455 struct audio_device *adev = out->dev;
456
457 if (adev->adm_abandon_focus)
458 adev->adm_abandon_focus(adev->adm_data, out->handle);
459}
460
461static void release_in_focus(struct stream_in *in, long ns __unused)
462{
463 struct audio_device *adev = in->dev;
464 if (adev->adm_abandon_focus)
465 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
466}
467
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700468static int parse_snd_card_status(struct str_parms * parms, int * card,
469 card_status_t * status)
470{
471 char value[32]={0};
472 char state[32]={0};
473
474 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
475
476 if (ret < 0)
477 return -1;
478
479 // sscanf should be okay as value is of max length 32.
480 // same as sizeof state.
481 if (sscanf(value, "%d,%s", card, state) < 2)
482 return -1;
483
484 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
485 CARD_STATUS_OFFLINE;
486 return 0;
487}
488
vivek mehta40125092017-08-21 18:48:51 -0700489// always call with adev lock held
490void send_gain_dep_calibration_l() {
491 if (last_known_cal_step >= 0)
492 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
493}
494
vivek mehta1a9b7c02015-06-25 11:49:38 -0700495__attribute__ ((visibility ("default")))
496bool audio_hw_send_gain_dep_calibration(int level) {
497 bool ret_val = false;
498 ALOGV("%s: enter ... ", __func__);
499
500 pthread_mutex_lock(&adev_init_lock);
501
502 if (adev != NULL && adev->platform != NULL) {
503 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700504 last_known_cal_step = level;
505 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700506 pthread_mutex_unlock(&adev->lock);
507 } else {
508 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
509 }
510
511 pthread_mutex_unlock(&adev_init_lock);
512
513 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
514 return ret_val;
515}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700516
jasmine cha270b7762018-03-30 15:41:33 +0800517#ifdef MAXXAUDIO_QDSP_ENABLED
518bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
519{
520 bool ret = false;
521 ALOGV("%s: enter ...", __func__);
522
523 pthread_mutex_lock(&adev_init_lock);
524
525 if (adev != NULL && adev->platform != NULL) {
526 pthread_mutex_lock(&adev->lock);
527 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
528 pthread_mutex_unlock(&adev->lock);
529 }
530
531 pthread_mutex_unlock(&adev_init_lock);
532
533 ALOGV("%s: exit with ret %d", __func__, ret);
534 return ret;
535}
536#else
537#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
538#endif
539
vivek mehtaa8d7c922016-05-25 14:40:44 -0700540__attribute__ ((visibility ("default")))
541int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
542 int table_size) {
543 int ret_val = 0;
544 ALOGV("%s: enter ... ", __func__);
545
546 pthread_mutex_lock(&adev_init_lock);
547 if (adev == NULL) {
548 ALOGW("%s: adev is NULL .... ", __func__);
549 goto done;
550 }
551
552 pthread_mutex_lock(&adev->lock);
553 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
554 pthread_mutex_unlock(&adev->lock);
555done:
556 pthread_mutex_unlock(&adev_init_lock);
557 ALOGV("%s: exit ... ", __func__);
558 return ret_val;
559}
560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700561static bool is_supported_format(audio_format_t format)
562{
Eric Laurent8251ac82014-07-23 11:00:25 -0700563 switch (format) {
564 case AUDIO_FORMAT_MP3:
565 case AUDIO_FORMAT_AAC_LC:
566 case AUDIO_FORMAT_AAC_HE_V1:
567 case AUDIO_FORMAT_AAC_HE_V2:
568 return true;
569 default:
570 break;
571 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700572 return false;
573}
574
juyuchenbe5c67e2018-08-29 17:19:20 +0800575static bool is_supported_24bits_audiosource(audio_source_t source)
576{
577 switch (source) {
578 case AUDIO_SOURCE_UNPROCESSED:
579#ifdef ENABLED_24BITS_CAMCORDER
580 case AUDIO_SOURCE_CAMCORDER:
581#endif
582 return true;
583 default:
584 break;
585 }
586 return false;
587}
588
Haynes Mathew George03c40102016-01-29 17:57:48 -0800589static inline bool is_mmap_usecase(audio_usecase_t uc_id)
590{
591 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
592 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
593}
594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700595static int get_snd_codec_id(audio_format_t format)
596{
597 int id = 0;
598
Eric Laurent8251ac82014-07-23 11:00:25 -0700599 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700600 case AUDIO_FORMAT_MP3:
601 id = SND_AUDIOCODEC_MP3;
602 break;
603 case AUDIO_FORMAT_AAC:
604 id = SND_AUDIOCODEC_AAC;
605 break;
606 default:
607 ALOGE("%s: Unsupported audio format", __func__);
608 }
609
610 return id;
611}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800612
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800613static int audio_ssr_status(struct audio_device *adev)
614{
615 int ret = 0;
616 struct mixer_ctl *ctl;
617 const char *mixer_ctl_name = "Audio SSR Status";
618
619 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
620 ret = mixer_ctl_get_value(ctl, 0);
621 ALOGD("%s: value: %d", __func__, ret);
622 return ret;
623}
624
vivek mehta4a824772017-06-08 19:05:49 -0700625static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
626{
627 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
628}
629
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800630static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
631{
632 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
633 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
634 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
635 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
636 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
637 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
638
639}
640
641static bool is_a2dp_device(snd_device_t out_snd_device)
642{
643 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
644}
645
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800646int enable_audio_route(struct audio_device *adev,
647 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800648{
yixuanjiang509f0a72018-09-06 18:37:23 +0800649 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700650 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800651
652 if (usecase == NULL)
653 return -EINVAL;
654
655 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
656
Carter Hsuaaa94962019-05-14 14:26:24 +0800657 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
658
Carter Hsub0c91482019-05-14 18:50:52 +0800659 if (usecase->type == PCM_CAPTURE) {
660 struct stream_in *in = usecase->stream.in;
661 struct audio_usecase *uinfo;
yixuanjiang509f0a72018-09-06 18:37:23 +0800662 snd_device = usecase->in_snd_device;
Carter Hsub0c91482019-05-14 18:50:52 +0800663
664 if (in) {
665 if (in->enable_aec || in->enable_ec_port) {
666 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
667 struct listnode *node;
668 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
669 USECASE_AUDIO_PLAYBACK_VOIP);
670 if (voip_usecase) {
671 out_device = voip_usecase->stream.out->devices;
672 } else if (adev->primary_output &&
673 !adev->primary_output->standby) {
674 out_device = adev->primary_output->devices;
675 } else {
676 list_for_each(node, &adev->usecase_list) {
677 uinfo = node_to_item(node, struct audio_usecase, list);
678 if (uinfo->type != PCM_CAPTURE) {
679 out_device = uinfo->stream.out->devices;
680 break;
681 }
682 }
683 }
684 platform_set_echo_reference(adev, true, out_device);
685 in->ec_opened = true;
686 }
687 }
688 } else
yixuanjiang509f0a72018-09-06 18:37:23 +0800689 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530690 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800691 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800692 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700693
694 // we shouldn't truncate mixer_path
695 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
696 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
697 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800698 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700699
Eric Laurent2e140aa2016-06-30 17:14:46 -0700700 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700701 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800703 ALOGV("%s: exit", __func__);
704 return 0;
705}
706
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800707int disable_audio_route(struct audio_device *adev,
708 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709{
yixuanjiang509f0a72018-09-06 18:37:23 +0800710 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700711 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800712
713 if (usecase == NULL)
714 return -EINVAL;
715
716 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800717 if (usecase->type == PCM_CAPTURE)
718 snd_device = usecase->in_snd_device;
719 else
720 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700721
722 // we shouldn't truncate mixer_path
723 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
724 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
725 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800726 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700727 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700728
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700729 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsub0c91482019-05-14 18:50:52 +0800730 if (usecase->type == PCM_CAPTURE) {
731 struct stream_in *in = usecase->stream.in;
732 if (in && in->ec_opened) {
733 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
734 in->ec_opened = false;
735 }
736 }
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000737 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800739 ALOGV("%s: exit", __func__);
740 return 0;
741}
742
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800743int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700744 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800745{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700746 int i, num_devices = 0;
747 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800748 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800749 if (snd_device < SND_DEVICE_MIN ||
750 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800751 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800752 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800753 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700754
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700755 platform_send_audio_calibration(adev->platform, snd_device);
756
vivek mehtade4849c2016-03-03 17:23:38 -0800757 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700758 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700759 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800760 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 }
762
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700763 /* due to the possibility of calibration overwrite between listen
764 and audio, notify sound trigger hal before audio calibration is sent */
765 audio_extn_sound_trigger_update_device_status(snd_device,
766 ST_EVENT_SND_DEVICE_BUSY);
767
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700768 if (audio_extn_spkr_prot_is_enabled())
769 audio_extn_spkr_prot_calib_cancel(adev);
770
zhaoyang yin4211fad2015-06-04 21:13:25 +0800771 audio_extn_dsm_feedback_enable(adev, snd_device, true);
772
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700773 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800774 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800775 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700776 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
777 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700778 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800779 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700780 }
781 if (audio_extn_spkr_prot_start_processing(snd_device)) {
782 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800783 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700784 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700785 } else if (platform_can_split_snd_device(snd_device,
786 &num_devices,
787 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700788 for (i = 0; i < num_devices; i++) {
789 enable_snd_device(adev, new_snd_devices[i]);
790 }
vivek mehtab6506412015-08-07 16:55:17 -0700791 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700792 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800793 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
794 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
795 ALOGE(" %s: Invalid sound device returned", __func__);
796 goto on_error;
797 }
Ed Tam70b5c142016-03-21 19:14:29 -0700798
Eric Laurent2e140aa2016-06-30 17:14:46 -0700799 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700800
801 if (is_a2dp_device(snd_device) &&
802 (audio_extn_a2dp_start_playback() < 0)) {
803 ALOGE("%s: failed to configure A2DP control path", __func__);
804 goto on_error;
805 }
806
vivek mehtade4849c2016-03-03 17:23:38 -0800807 audio_route_apply_and_update_path(adev->audio_route, device_name);
808 }
809on_success:
810 adev->snd_dev_ref_cnt[snd_device]++;
811 ret_val = 0;
812on_error:
813 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814}
815
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800816int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700817 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700819 int i, num_devices = 0;
820 snd_device_t new_snd_devices[2];
821
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800822 if (snd_device < SND_DEVICE_MIN ||
823 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800824 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800825 return -EINVAL;
826 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
828 ALOGE("%s: device ref cnt is already 0", __func__);
829 return -EINVAL;
830 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800831 audio_extn_tfa_98xx_disable_speaker(snd_device);
832
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700833 adev->snd_dev_ref_cnt[snd_device]--;
834 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800835 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800836
837 if (is_a2dp_device(snd_device))
838 audio_extn_a2dp_stop_playback();
839
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700840 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800841 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700842 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700843 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
844 audio_extn_spkr_prot_is_enabled()) {
845 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700846
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700847 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
848 // and does not use speaker swap. As this code causes a problem with device enable ref
849 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700850 // when speaker device is disabled, reset swap.
851 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700852 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700853
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700854 } else if (platform_can_split_snd_device(snd_device,
855 &num_devices,
856 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700857 for (i = 0; i < num_devices; i++) {
858 disable_snd_device(adev, new_snd_devices[i]);
859 }
vivek mehtab6506412015-08-07 16:55:17 -0700860 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700861 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800862 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
863 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
864 ALOGE(" %s: Invalid sound device returned", __func__);
865 return -EINVAL;
866 }
867
Eric Laurent2e140aa2016-06-30 17:14:46 -0700868 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800869 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700870 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700871 audio_extn_sound_trigger_update_device_status(snd_device,
872 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
vivek mehtab6506412015-08-07 16:55:17 -0700874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800875 return 0;
876}
877
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800878#ifdef DYNAMIC_ECNS_ENABLED
879static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
880 struct stream_in *in,
881 struct audio_effect_config effect_config,
882 unsigned int param_value)
883{
884 char mixer_ctl_name[] = "Audio Effect";
885 long set_values[6];
886
887 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
888 if (!ctl) {
889 ALOGE("%s: Could not get mixer ctl - %s",
890 __func__, mixer_ctl_name);
891 return -EINVAL;
892 }
893
894 set_values[0] = 1; //0:Rx 1:Tx
895 set_values[1] = in->app_type_cfg.app_type;
896 set_values[2] = (long)effect_config.module_id;
897 set_values[3] = (long)effect_config.instance_id;
898 set_values[4] = (long)effect_config.param_id;
899 set_values[5] = param_value;
900
901 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
902
903 return 0;
904
905}
906
907static int update_effect_param_ecns(struct audio_usecase *usecase,
908 unsigned int module_id, int effect_type,
909 unsigned int *param_value)
910{
911 int ret = 0;
912 struct audio_effect_config other_effect_config;
913 struct stream_in *in = NULL;
914
915 if (!usecase)
916 return -EINVAL;
917
918 in = usecase->stream.in;
919
920 /* Get the effect config data of the other effect */
921 ret = platform_get_effect_config_data(usecase->in_snd_device,
922 &other_effect_config,
923 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
924 if (ret < 0) {
925 ALOGE("%s Failed to get effect params %d", __func__, ret);
926 return ret;
927 }
928
929 if (module_id == other_effect_config.module_id) {
930 //Same module id for AEC/NS. Values need to be combined
931 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
932 ((effect_type == EFFECT_NS) && (in->enable_aec)))
933 *param_value |= other_effect_config.param_value;
934 }
935
936 return ret;
937}
938
939static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
940 int effect_type, bool enable)
941{
942 struct audio_effect_config effect_config;
943 struct audio_usecase *usecase = NULL;
944 int ret = 0;
945 unsigned int param_value = 0;
946
947 if (!in) {
948 ALOGE("%s: Invalid input stream", __func__);
949 return -EINVAL;
950 }
951
952 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
953
954 usecase = get_usecase_from_list(adev, in->usecase);
955
956 ret = platform_get_effect_config_data(usecase->in_snd_device,
957 &effect_config, effect_type);
958 if (ret < 0) {
959 ALOGE("%s Failed to get module id %d", __func__, ret);
960 return ret;
961 }
962 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
963 __func__, effect_config.module_id, in->app_type_cfg.app_type,
964 usecase->id, usecase->in_snd_device);
965
966 if (enable)
967 param_value = effect_config.param_value;
968
969 /*Special handling for AEC & NS effects Param values need to be
970 updated if module ids are same*/
971
972 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
973 ret = update_effect_param_ecns(usecase, effect_config.module_id,
974 effect_type, &param_value);
975 if (ret < 0)
976 return ret;
977 }
978
979 ret = send_effect_enable_disable_mixer_ctl(adev, in,
980 effect_config, param_value);
981
982 return ret;
983}
984
985static int check_and_enable_effect(struct audio_device *adev)
986{
987 int ret = 0;
988
989 struct listnode *node;
990 struct stream_in *in = NULL;
991
992 list_for_each(node, &adev->usecase_list)
993 {
994 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
995 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
996 in = usecase->stream.in;
997
998 if (in->standby)
999 continue;
1000
1001 if (in->enable_aec) {
1002 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
1003 }
1004
1005 if (in->enable_ns &&
1006 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1007 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
1008 }
1009 }
1010 }
1011
1012 return ret;
1013}
1014#else
1015#define enable_disable_effect(w, x, y, z) -ENOSYS
1016#define check_and_enable_effect(x) -ENOSYS
1017#endif
1018
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001019/*
1020 legend:
1021 uc - existing usecase
1022 new_uc - new usecase
1023 d1, d11, d2 - SND_DEVICE enums
1024 a1, a2 - corresponding ANDROID device enums
1025 B, B1, B2 - backend strings
1026
1027case 1
1028 uc->dev d1 (a1) B1
1029 new_uc->dev d1 (a1), d2 (a2) B1, B2
1030
1031 resolution: disable and enable uc->dev on d1
1032
1033case 2
1034 uc->dev d1 (a1) B1
1035 new_uc->dev d11 (a1) B1
1036
1037 resolution: need to switch uc since d1 and d11 are related
1038 (e.g. speaker and voice-speaker)
1039 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1040
1041case 3
1042 uc->dev d1 (a1) B1
1043 new_uc->dev d2 (a2) B2
1044
1045 resolution: no need to switch uc
1046
1047case 4
1048 uc->dev d1 (a1) B
1049 new_uc->dev d2 (a2) B
1050
1051 resolution: disable enable uc-dev on d2 since backends match
1052 we cannot enable two streams on two different devices if they
1053 share the same backend. e.g. if offload is on speaker device using
1054 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1055 using the same backend, offload must also be switched to voice-handset.
1056
1057case 5
1058 uc->dev d1 (a1) B
1059 new_uc->dev d1 (a1), d2 (a2) B
1060
1061 resolution: disable enable uc-dev on d2 since backends match
1062 we cannot enable two streams on two different devices if they
1063 share the same backend.
1064
1065case 6
1066 uc->dev d1 a1 B1
1067 new_uc->dev d2 a1 B2
1068
1069 resolution: no need to switch
1070
1071case 7
1072
1073 uc->dev d1 (a1), d2 (a2) B1, B2
1074 new_uc->dev d1 B1
1075
1076 resolution: no need to switch
1077
1078*/
1079static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1080 struct audio_usecase *new_uc,
1081 snd_device_t new_snd_device)
1082{
1083 audio_devices_t a1 = uc->stream.out->devices;
1084 audio_devices_t a2 = new_uc->stream.out->devices;
1085
1086 snd_device_t d1 = uc->out_snd_device;
1087 snd_device_t d2 = new_snd_device;
1088
1089 // Treat as a special case when a1 and a2 are not disjoint
1090 if ((a1 != a2) && (a1 & a2)) {
1091 snd_device_t d3[2];
1092 int num_devices = 0;
1093 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1094 &num_devices,
1095 d3);
1096 if (ret < 0) {
1097 if (ret != -ENOSYS) {
1098 ALOGW("%s failed to split snd_device %d",
1099 __func__,
1100 popcount(a1) > 1 ? d1 : d2);
1101 }
1102 goto end;
1103 }
1104
1105 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1106 // But if it does happen, we need to give priority to d2 if
1107 // the combo devices active on the existing usecase share a backend.
1108 // This is because we cannot have a usecase active on a combo device
1109 // and a new usecase requests one device in this combo pair.
1110 if (platform_check_backends_match(d3[0], d3[1])) {
1111 return d2; // case 5
1112 } else {
1113 return d1; // case 1
1114 }
1115 } else {
1116 if (platform_check_backends_match(d1, d2)) {
1117 return d2; // case 2, 4
1118 } else {
1119 return d1; // case 6, 3
1120 }
1121 }
1122
1123end:
1124 return d2; // return whatever was calculated before.
1125}
1126
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001127static void check_and_route_playback_usecases(struct audio_device *adev,
1128 struct audio_usecase *uc_info,
1129 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130{
1131 struct listnode *node;
1132 struct audio_usecase *usecase;
1133 bool switch_device[AUDIO_USECASE_MAX];
1134 int i, num_uc_to_switch = 0;
1135
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001136 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1137 uc_info,
1138 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001139
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001140 /* For a2dp device reconfigure all active sessions
1141 * with new AFE encoder format based on a2dp state
1142 */
1143 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001144 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1145 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001146 audio_extn_a2dp_is_force_device_switch()) {
1147 force_routing = true;
1148 }
1149
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 /*
1151 * This function is to make sure that all the usecases that are active on
1152 * the hardware codec backend are always routed to any one device that is
1153 * handled by the hardware codec.
1154 * For example, if low-latency and deep-buffer usecases are currently active
1155 * on speaker and out_set_parameters(headset) is received on low-latency
1156 * output, then we have to make sure deep-buffer is also switched to headset,
1157 * because of the limitation that both the devices cannot be enabled
1158 * at the same time as they share the same backend.
1159 */
1160 /* Disable all the usecases on the shared backend other than the
1161 specified usecase */
1162 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1163 switch_device[i] = false;
1164
1165 list_for_each(node, &adev->usecase_list) {
1166 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001167 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1168 continue;
1169
1170 if (force_routing ||
1171 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001172 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1173 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001174 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1176 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001177 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001178 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 switch_device[usecase->id] = true;
1180 num_uc_to_switch++;
1181 }
1182 }
1183
1184 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 list_for_each(node, &adev->usecase_list) {
1186 usecase = node_to_item(node, struct audio_usecase, list);
1187 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001188 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001189 }
1190 }
1191
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001192 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001193 list_for_each(node, &adev->usecase_list) {
1194 usecase = node_to_item(node, struct audio_usecase, list);
1195 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001196 d_device = derive_playback_snd_device(usecase, uc_info,
1197 snd_device);
1198 enable_snd_device(adev, d_device);
1199 /* Update the out_snd_device before enabling the audio route */
1200 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 }
1202 }
1203
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 /* Re-route all the usecases on the shared backend other than the
1205 specified usecase to new snd devices */
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001208 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001209 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 }
1211 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212 }
1213}
1214
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001215static void check_and_route_capture_usecases(struct audio_device *adev,
1216 struct audio_usecase *uc_info,
1217 snd_device_t snd_device)
1218{
1219 struct listnode *node;
1220 struct audio_usecase *usecase;
1221 bool switch_device[AUDIO_USECASE_MAX];
1222 int i, num_uc_to_switch = 0;
1223
vivek mehta4ed66e62016-04-15 23:33:34 -07001224 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1225
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001226 /*
1227 * This function is to make sure that all the active capture usecases
1228 * are always routed to the same input sound device.
1229 * For example, if audio-record and voice-call usecases are currently
1230 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1231 * is received for voice call then we have to make sure that audio-record
1232 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1233 * because of the limitation that two devices cannot be enabled
1234 * at the same time if they share the same backend.
1235 */
1236 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1237 switch_device[i] = false;
1238
1239 list_for_each(node, &adev->usecase_list) {
1240 usecase = node_to_item(node, struct audio_usecase, list);
1241 if (usecase->type != PCM_PLAYBACK &&
1242 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001243 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001244 ((uc_info->type == VOICE_CALL &&
1245 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1246 platform_check_backends_match(snd_device,\
1247 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001248 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001249 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1250 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001251 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001252 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001253 switch_device[usecase->id] = true;
1254 num_uc_to_switch++;
1255 }
1256 }
1257
1258 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001259 list_for_each(node, &adev->usecase_list) {
1260 usecase = node_to_item(node, struct audio_usecase, list);
1261 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001262 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001263 }
1264 }
1265
1266 list_for_each(node, &adev->usecase_list) {
1267 usecase = node_to_item(node, struct audio_usecase, list);
1268 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001269 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001270 }
1271 }
1272
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001273 /* Re-route all the usecases on the shared backend other than the
1274 specified usecase to new snd devices */
1275 list_for_each(node, &adev->usecase_list) {
1276 usecase = node_to_item(node, struct audio_usecase, list);
1277 /* Update the in_snd_device only before enabling the audio route */
1278 if (switch_device[usecase->id] ) {
1279 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001280 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001281 }
1282 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001283 }
1284}
1285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001286/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001287static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001289 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001290 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001291
1292 switch (channels) {
1293 /*
1294 * Do not handle stereo output in Multi-channel cases
1295 * Stereo case is handled in normal playback path
1296 */
1297 case 6:
1298 ALOGV("%s: HDMI supports 5.1", __func__);
1299 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1300 break;
1301 case 8:
1302 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1303 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1304 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1305 break;
1306 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001307 ALOGE("HDMI does not support multi channel playback");
1308 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 break;
1310 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001311 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312}
1313
Andy Hung18859412017-08-09 11:47:21 -07001314static ssize_t read_usb_sup_sample_rates(bool is_playback,
1315 uint32_t *supported_sample_rates,
1316 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001317{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001318 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1319 supported_sample_rates,
1320 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001321#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001322 for (ssize_t i=0; i<count; i++) {
1323 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1324 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001325 }
1326#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001327 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001328}
1329
Haynes Mathew George569b7482017-05-08 14:44:27 -07001330static int read_usb_sup_channel_masks(bool is_playback,
1331 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001332 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001333{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001334 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001335 int channel_count;
1336 uint32_t num_masks = 0;
1337 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1338 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001339 }
Eric Laurent74b55762017-07-09 17:04:53 -07001340 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001341 // start from 2 channels as framework currently doesn't support mono.
Eric Laurent154055d2019-05-01 18:07:29 -07001342 if (channels >= FCC_2) {
1343 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
Eric Laurent74b55762017-07-09 17:04:53 -07001344 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001345 for (channel_count = FCC_2;
1346 channel_count <= channels && num_masks < max_masks;
1347 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001348 supported_channel_masks[num_masks++] =
1349 audio_channel_mask_for_index_assignment_from_count(channel_count);
1350 }
1351 } else {
1352 // For capture we report all supported channel masks from 1 channel up.
1353 channel_count = MIN_CHANNEL_COUNT;
1354 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1355 // indexed mask
1356 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Eric Laurent154055d2019-05-01 18:07:29 -07001357 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1358 if (channel_count <= FCC_2) {
1359 mask = audio_channel_in_mask_from_count(channel_count);
1360 supported_channel_masks[num_masks++] = mask;
1361 }
Andy Hung88ce1d92018-10-29 18:31:12 -07001362 const audio_channel_mask_t index_mask =
1363 audio_channel_mask_for_index_assignment_from_count(channel_count);
1364 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1365 supported_channel_masks[num_masks++] = index_mask;
1366 }
Eric Laurent74b55762017-07-09 17:04:53 -07001367 }
1368 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001369#ifdef NDEBUG
1370 for (size_t i = 0; i < num_masks; ++i) {
1371 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1372 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1373 }
1374#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001375 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001376}
1377
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001378static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001379 audio_format_t *supported_formats,
1380 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001381{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001382 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001383 switch (bitwidth) {
1384 case 24:
1385 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001386 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001387 break;
1388 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001389 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001390 break;
1391 case 16:
1392 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001393 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001394 break;
1395 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001396 ALOGV("%s: %s supported format %d", __func__,
1397 is_playback ? "P" : "C", bitwidth);
1398 return 1;
1399}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001400
Haynes Mathew George569b7482017-05-08 14:44:27 -07001401static int read_usb_sup_params_and_compare(bool is_playback,
1402 audio_format_t *format,
1403 audio_format_t *supported_formats,
1404 uint32_t max_formats,
1405 audio_channel_mask_t *mask,
1406 audio_channel_mask_t *supported_channel_masks,
1407 uint32_t max_masks,
1408 uint32_t *rate,
1409 uint32_t *supported_sample_rates,
1410 uint32_t max_rates) {
1411 int ret = 0;
1412 int num_formats;
1413 int num_masks;
1414 int num_rates;
1415 int i;
1416
1417 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1418 max_formats);
1419 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1420 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001421
Haynes Mathew George569b7482017-05-08 14:44:27 -07001422 num_rates = read_usb_sup_sample_rates(is_playback,
1423 supported_sample_rates, max_rates);
1424
1425#define LUT(table, len, what, dflt) \
1426 for (i=0; i<len && (table[i] != what); i++); \
1427 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1428
1429 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1430 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1431 LUT(supported_sample_rates, num_rates, *rate, 0);
1432
1433#undef LUT
1434 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001435}
1436
Andy Hungd9653bd2017-08-01 19:31:39 -07001437static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1438{
1439 // Check if usb is ready.
1440 // The usb device may have been removed quickly after insertion and hence
1441 // no longer available. This will show up as empty channel masks, or rates.
1442
1443 pthread_mutex_lock(&adev->lock);
1444 uint32_t supported_sample_rate;
1445
1446 // we consider usb ready if we can fetch at least one sample rate.
1447 const bool ready = read_usb_sup_sample_rates(
1448 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1449 pthread_mutex_unlock(&adev->lock);
1450 return ready;
1451}
1452
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001453static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1454{
1455 struct audio_usecase *usecase;
1456 struct listnode *node;
1457
1458 list_for_each(node, &adev->usecase_list) {
1459 usecase = node_to_item(node, struct audio_usecase, list);
1460 if (usecase->type == VOICE_CALL) {
1461 ALOGV("%s: usecase id %d", __func__, usecase->id);
1462 return usecase->id;
1463 }
1464 }
1465 return USECASE_INVALID;
1466}
1467
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001468struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1469 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470{
1471 struct audio_usecase *usecase;
1472 struct listnode *node;
1473
1474 list_for_each(node, &adev->usecase_list) {
1475 usecase = node_to_item(node, struct audio_usecase, list);
1476 if (usecase->id == uc_id)
1477 return usecase;
1478 }
1479 return NULL;
1480}
1481
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001482static bool force_device_switch(struct audio_usecase *usecase)
1483{
Carter Hsuaaa94962019-05-14 14:26:24 +08001484 if (usecase->type == PCM_CAPTURE || usecase->stream.out == NULL) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001485 return false;
1486 }
1487
1488 // Force all A2DP output devices to reconfigure for proper AFE encode format
1489 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1490 // in suspended state, hence try to trigger a retry when we again get a routing request.
1491 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1492 audio_extn_a2dp_is_force_device_switch()) {
1493 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1494 return true;
1495 }
1496
1497 return false;
1498}
1499
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001500struct stream_in *adev_get_active_input(const struct audio_device *adev)
1501{
1502 struct listnode *node;
1503 struct stream_in *last_active_in = NULL;
1504
1505 /* Get last added active input.
1506 * TODO: We may use a priority mechanism to pick highest priority active source */
1507 list_for_each(node, &adev->usecase_list)
1508 {
1509 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1510 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1511 last_active_in = usecase->stream.in;
1512 }
1513 }
1514
1515 return last_active_in;
1516}
1517
1518struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1519{
1520 struct listnode *node;
1521
1522 /* First check active inputs with voice communication source and then
1523 * any input if audio mode is in communication */
1524 list_for_each(node, &adev->usecase_list)
1525 {
1526 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1527 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1528 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1529 return usecase->stream.in;
1530 }
1531 }
1532 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1533 return adev_get_active_input(adev);
1534 }
1535 return NULL;
1536}
1537
Carter Hsub0c91482019-05-14 18:50:52 +08001538/*
1539 * Aligned with policy.h
1540 */
1541static inline int source_priority(int inputSource)
1542{
1543 switch (inputSource) {
1544 case AUDIO_SOURCE_VOICE_COMMUNICATION:
1545 return 9;
1546 case AUDIO_SOURCE_CAMCORDER:
1547 return 8;
1548 case AUDIO_SOURCE_VOICE_PERFORMANCE:
1549 return 7;
1550 case AUDIO_SOURCE_UNPROCESSED:
1551 return 6;
1552 case AUDIO_SOURCE_MIC:
1553 return 5;
1554 case AUDIO_SOURCE_ECHO_REFERENCE:
1555 return 4;
1556 case AUDIO_SOURCE_FM_TUNER:
1557 return 3;
1558 case AUDIO_SOURCE_VOICE_RECOGNITION:
1559 return 2;
1560 case AUDIO_SOURCE_HOTWORD:
1561 return 1;
1562 default:
1563 break;
1564 }
1565 return 0;
1566}
1567
1568static struct stream_in *get_priority_input(struct audio_device *adev)
1569{
1570 struct listnode *node;
1571 struct audio_usecase *usecase;
1572 int last_priority = 0, priority;
1573 struct stream_in *priority_in = NULL;
1574 struct stream_in *in;
1575
1576 list_for_each(node, &adev->usecase_list) {
1577 usecase = node_to_item(node, struct audio_usecase, list);
1578 if (usecase->type == PCM_CAPTURE) {
1579 in = usecase->stream.in;
1580 if (!in)
1581 continue;
1582 priority = source_priority(in->source);
1583
1584 if (priority > last_priority) {
1585 last_priority = priority;
1586 priority_in = in;
1587 }
1588 }
1589 }
1590 return priority_in;
1591}
1592
HW Leef88584d2019-03-18 17:27:18 +08001593int select_devices_with_force_switch(struct audio_device *adev,
1594 audio_usecase_t uc_id,
1595 bool force_switch)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001597 snd_device_t out_snd_device = SND_DEVICE_NONE;
1598 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 struct audio_usecase *usecase = NULL;
1600 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001601 struct audio_usecase *hfp_usecase = NULL;
1602 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001603 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001604 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001605 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1606 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001607
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 usecase = get_usecase_from_list(adev, uc_id);
1609 if (usecase == NULL) {
1610 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1611 return -EINVAL;
1612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001614 if ((usecase->type == VOICE_CALL) ||
1615 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001616 out_snd_device = platform_get_output_snd_device(adev->platform,
1617 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001618 in_snd_device = platform_get_input_snd_device(adev->platform,
1619 NULL,
1620 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621 usecase->devices = usecase->stream.out->devices;
1622 } else {
1623 /*
1624 * If the voice call is active, use the sound devices of voice call usecase
1625 * so that it would not result any device switch. All the usecases will
1626 * be switched to new device when select_devices() is called for voice call
1627 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001628 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001630 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001631 vc_usecase = get_usecase_from_list(adev,
1632 get_voice_usecase_id_from_list(adev));
1633 if ((vc_usecase != NULL) &&
1634 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001635 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1636 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001637 in_snd_device = vc_usecase->in_snd_device;
1638 out_snd_device = vc_usecase->out_snd_device;
1639 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001640 } else if (audio_extn_hfp_is_active(adev)) {
1641 hfp_ucid = audio_extn_hfp_get_usecase();
1642 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1643 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1644 in_snd_device = hfp_usecase->in_snd_device;
1645 out_snd_device = hfp_usecase->out_snd_device;
1646 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 }
1648 if (usecase->type == PCM_PLAYBACK) {
1649 usecase->devices = usecase->stream.out->devices;
1650 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001651 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001652 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001653 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001654
Eric Laurentb23d5282013-05-14 15:27:20 -07001655 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001656 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001657
1658 if (voip_usecase)
1659 voip_out = voip_usecase->stream.out;
1660
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001661 if (usecase->stream.out == voip_out && voip_in != NULL) {
1662 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001663 }
1664 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665 } else if (usecase->type == PCM_CAPTURE) {
1666 usecase->devices = usecase->stream.in->device;
1667 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001668 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001669 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001670 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsub0c91482019-05-14 18:50:52 +08001671 struct stream_in *priority_in = NULL;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001672
1673 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001674 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1675 USECASE_AUDIO_PLAYBACK_VOIP);
1676
Carter Hsub0c91482019-05-14 18:50:52 +08001677 usecase->stream.in->enable_ec_port = false;
1678
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001679 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1680 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001681 } else if (voip_usecase) {
1682 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001683 } else if (adev->primary_output &&
1684 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001685 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001686 } else {
1687 /* forcing speaker o/p device to get matching i/p pair
1688 in case o/p is not routed from same primary HAL */
1689 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001690 }
Carter Hsub0c91482019-05-14 18:50:52 +08001691 priority_in = voip_in;
1692 } else {
1693 /* get the input with the highest priority source*/
1694 priority_in = get_priority_input(adev);
1695
1696 if (!priority_in)
1697 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001698 }
Carter Hsub0c91482019-05-14 18:50:52 +08001699
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001700 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsub0c91482019-05-14 18:50:52 +08001701 priority_in,
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001702 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704 }
1705 }
1706
1707 if (out_snd_device == usecase->out_snd_device &&
1708 in_snd_device == usecase->in_snd_device) {
HW Leef88584d2019-03-18 17:27:18 +08001709 if (!force_device_switch(usecase) && !force_switch)
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001710 return 0;
1711 }
1712
1713 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1714 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1715 return 0;
1716 }
1717
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001718 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1719 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001720 (!audio_extn_a2dp_is_ready())) {
1721 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001722 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1723 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1724 else
1725 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726 }
1727
juyuchen66c4ecf2018-08-06 15:39:34 +08001728 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1729 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1730 }
1731
Eric Laurent2bafff12016-03-17 12:17:23 -07001732 if (out_snd_device != SND_DEVICE_NONE &&
1733 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1734 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1735 __func__,
1736 use_case_table[uc_id],
1737 adev->last_logged_snd_device[uc_id][0],
1738 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1739 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1740 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1741 -1,
1742 out_snd_device,
1743 platform_get_snd_device_name(out_snd_device),
1744 platform_get_snd_device_acdb_id(out_snd_device));
1745 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1746 }
1747 if (in_snd_device != SND_DEVICE_NONE &&
1748 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1749 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1750 __func__,
1751 use_case_table[uc_id],
1752 adev->last_logged_snd_device[uc_id][1],
1753 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1754 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1755 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1756 -1,
1757 in_snd_device,
1758 platform_get_snd_device_name(in_snd_device),
1759 platform_get_snd_device_acdb_id(in_snd_device));
1760 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1761 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 /*
1764 * Limitation: While in call, to do a device switch we need to disable
1765 * and enable both RX and TX devices though one of them is same as current
1766 * device.
1767 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001768 if ((usecase->type == VOICE_CALL) &&
1769 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1770 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001771 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001772 /* Disable sidetone only if voice call already exists */
1773 if (voice_is_call_state_active(adev))
1774 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001775 }
1776
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001777 /* Disable current sound devices */
1778 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001779 disable_audio_route(adev, usecase);
1780 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 }
1782
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001783 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001784 disable_audio_route(adev, usecase);
1785 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 }
1787
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001788 /* Applicable only on the targets that has external modem.
1789 * New device information should be sent to modem before enabling
1790 * the devices to reduce in-call device switch time.
1791 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001792 if ((usecase->type == VOICE_CALL) &&
1793 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1794 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001795 status = platform_switch_voice_call_enable_device_config(adev->platform,
1796 out_snd_device,
1797 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001798 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001799
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001800 /* Enable new sound devices */
1801 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001802 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001803 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1804 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001805 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001806 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 }
1808
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001809 if (in_snd_device != SND_DEVICE_NONE) {
1810 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001811 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001812 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813
Eric Laurentb23d5282013-05-14 15:27:20 -07001814 if (usecase->type == VOICE_CALL)
1815 status = platform_switch_voice_call_device_post(adev->platform,
1816 out_snd_device,
1817 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001818
sangwoo170731f2013-06-08 15:36:36 +09001819 usecase->in_snd_device = in_snd_device;
1820 usecase->out_snd_device = out_snd_device;
1821
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001822 audio_extn_tfa_98xx_set_mode();
1823
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001824 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001825
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001826 /* If input stream is already running the effect needs to be
1827 applied on the new input device that's being enabled here. */
1828 if (in_snd_device != SND_DEVICE_NONE)
1829 check_and_enable_effect(adev);
1830
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001831 /* Applicable only on the targets that has external modem.
1832 * Enable device command should be sent to modem only after
1833 * enabling voice call mixer controls
1834 */
vivek mehta765eb642015-08-07 19:46:06 -07001835 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001836 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1837 out_snd_device,
1838 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001839 /* Enable sidetone only if voice call already exists */
1840 if (voice_is_call_state_active(adev))
1841 voice_set_sidetone(adev, out_snd_device, true);
1842 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001843
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001844 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001845 struct stream_out *voip_out = voip_usecase->stream.out;
1846 audio_extn_utils_send_app_type_gain(adev,
1847 voip_out->app_type_cfg.app_type,
1848 &voip_out->app_type_cfg.gain[0]);
1849 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 return status;
1851}
1852
HW Leef88584d2019-03-18 17:27:18 +08001853int select_devices(struct audio_device *adev,
1854 audio_usecase_t uc_id)
1855{
1856 return select_devices_with_force_switch(adev, uc_id, false);
1857}
1858
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859static int stop_input_stream(struct stream_in *in)
1860{
1861 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 struct audio_usecase *uc_info;
1863 struct audio_device *adev = in->dev;
Carter Hsub0c91482019-05-14 18:50:52 +08001864 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865
Eric Laurent994a6932013-07-17 11:51:42 -07001866 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 uc_info = get_usecase_from_list(adev, in->usecase);
1870 if (uc_info == NULL) {
1871 ALOGE("%s: Could not find the usecase (%d) in the list",
1872 __func__, in->usecase);
1873 return -EINVAL;
1874 }
1875
Carter Hsub0c91482019-05-14 18:50:52 +08001876 priority_in = get_priority_input(adev);
1877
vivek mehta781065c2017-04-04 12:55:01 -07001878 /* Close in-call recording streams */
1879 voice_check_and_stop_incall_rec_usecase(adev, in);
1880
Eric Laurent150dbfe2013-02-27 14:31:02 -08001881 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001882 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001883
1884 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001885 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001887 list_remove(&uc_info->list);
1888 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001889
Carter Hsub0c91482019-05-14 18:50:52 +08001890 if (priority_in == in) {
1891 priority_in = get_priority_input(adev);
1892 if (priority_in)
1893 select_devices(adev, priority_in->usecase);
1894 }
1895
Eric Laurent994a6932013-07-17 11:51:42 -07001896 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 return ret;
1898}
1899
1900int start_input_stream(struct stream_in *in)
1901{
1902 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001903 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001904 struct audio_usecase *uc_info;
1905 struct audio_device *adev = in->dev;
1906
Eric Laurent994a6932013-07-17 11:51:42 -07001907 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001908
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001909 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1910 return -EIO;
1911
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001912 if (in->card_status == CARD_STATUS_OFFLINE ||
1913 adev->card_status == CARD_STATUS_OFFLINE) {
1914 ALOGW("in->card_status or adev->card_status offline, try again");
1915 ret = -EAGAIN;
1916 goto error_config;
1917 }
1918
vivek mehta781065c2017-04-04 12:55:01 -07001919 /* Check if source matches incall recording usecase criteria */
1920 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1921 if (ret)
1922 goto error_config;
1923 else
1924 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1925
Eric Laurentb23d5282013-05-14 15:27:20 -07001926 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927 if (in->pcm_device_id < 0) {
1928 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1929 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001930 ret = -EINVAL;
1931 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1935 uc_info->id = in->usecase;
1936 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001937 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001938 uc_info->devices = in->device;
1939 uc_info->in_snd_device = SND_DEVICE_NONE;
1940 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001942 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001943
Wei Wangf4837d52017-11-21 14:51:20 -08001944 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001945 audio_extn_perf_lock_acquire();
1946
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001947 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948
Eric Laurent0e46adf2016-12-16 12:49:24 -08001949 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001950 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001951 ALOGE("%s: pcm stream not ready", __func__);
1952 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001953 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001954 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001955 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001956 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1957 goto error_open;
1958 }
1959 } else {
1960 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1961 unsigned int pcm_open_retry_count = 0;
1962
1963 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1964 flags |= PCM_MMAP | PCM_NOIRQ;
1965 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1966 } else if (in->realtime) {
1967 flags |= PCM_MMAP | PCM_NOIRQ;
1968 }
1969
1970 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1971 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1972
1973 while (1) {
1974 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1975 flags, &in->config);
1976 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1977 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1978 if (in->pcm != NULL) {
1979 pcm_close(in->pcm);
1980 in->pcm = NULL;
1981 }
1982 if (pcm_open_retry_count-- == 0) {
1983 ret = -EIO;
1984 goto error_open;
1985 }
1986 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1987 continue;
1988 }
1989 break;
1990 }
1991
1992 ALOGV("%s: pcm_prepare", __func__);
1993 ret = pcm_prepare(in->pcm);
1994 if (ret < 0) {
1995 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001996 pcm_close(in->pcm);
1997 in->pcm = NULL;
1998 goto error_open;
1999 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002000 if (in->realtime) {
2001 ret = pcm_start(in->pcm);
2002 if (ret < 0) {
2003 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2004 pcm_close(in->pcm);
2005 in->pcm = NULL;
2006 goto error_open;
2007 }
2008 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002009 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002010 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08002011 check_and_enable_effect(adev);
justinwengc6347db2019-02-21 18:49:00 +08002012 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2013 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Wei Wangf4837d52017-11-21 14:51:20 -08002014 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002015 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07002016 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002017
Eric Laurent0e46adf2016-12-16 12:49:24 -08002018 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08002019
2020error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08002022 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002023 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08002024
2025error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07002026 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08002027 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028}
2029
Eric Laurenta1478072015-09-21 17:21:52 -07002030void lock_input_stream(struct stream_in *in)
2031{
2032 pthread_mutex_lock(&in->pre_lock);
2033 pthread_mutex_lock(&in->lock);
2034 pthread_mutex_unlock(&in->pre_lock);
2035}
2036
2037void lock_output_stream(struct stream_out *out)
2038{
2039 pthread_mutex_lock(&out->pre_lock);
2040 pthread_mutex_lock(&out->lock);
2041 pthread_mutex_unlock(&out->pre_lock);
2042}
2043
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044/* must be called with out->lock locked */
2045static int send_offload_cmd_l(struct stream_out* out, int command)
2046{
2047 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2048
2049 ALOGVV("%s %d", __func__, command);
2050
2051 cmd->cmd = command;
2052 list_add_tail(&out->offload_cmd_list, &cmd->node);
2053 pthread_cond_signal(&out->offload_cond);
2054 return 0;
2055}
2056
2057/* must be called iwth out->lock locked */
2058static void stop_compressed_output_l(struct stream_out *out)
2059{
2060 out->offload_state = OFFLOAD_STATE_IDLE;
2061 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002062 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 if (out->compr != NULL) {
2064 compress_stop(out->compr);
2065 while (out->offload_thread_blocked) {
2066 pthread_cond_wait(&out->cond, &out->lock);
2067 }
2068 }
2069}
2070
2071static void *offload_thread_loop(void *context)
2072{
2073 struct stream_out *out = (struct stream_out *) context;
2074 struct listnode *item;
2075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
2077 set_sched_policy(0, SP_FOREGROUND);
2078 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2079
2080 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08002081
Eric Laurenta1478072015-09-21 17:21:52 -07002082 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08002083 out->offload_state = OFFLOAD_STATE_IDLE;
2084 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085 for (;;) {
2086 struct offload_cmd *cmd = NULL;
2087 stream_callback_event_t event;
2088 bool send_callback = false;
2089
2090 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2091 __func__, list_empty(&out->offload_cmd_list),
2092 out->offload_state);
2093 if (list_empty(&out->offload_cmd_list)) {
2094 ALOGV("%s SLEEPING", __func__);
2095 pthread_cond_wait(&out->offload_cond, &out->lock);
2096 ALOGV("%s RUNNING", __func__);
2097 continue;
2098 }
2099
2100 item = list_head(&out->offload_cmd_list);
2101 cmd = node_to_item(item, struct offload_cmd, node);
2102 list_remove(item);
2103
2104 ALOGVV("%s STATE %d CMD %d out->compr %p",
2105 __func__, out->offload_state, cmd->cmd, out->compr);
2106
2107 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2108 free(cmd);
2109 break;
2110 }
2111
2112 if (out->compr == NULL) {
2113 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07002114 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 pthread_cond_signal(&out->cond);
2116 continue;
2117 }
2118 out->offload_thread_blocked = true;
2119 pthread_mutex_unlock(&out->lock);
2120 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002121 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002122 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2123 compress_wait(out->compr, -1);
2124 send_callback = true;
2125 event = STREAM_CBK_EVENT_WRITE_READY;
2126 break;
2127 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 compress_next_track(out->compr);
2129 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 send_callback = true;
2131 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002132 /* Resend the metadata for next iteration */
2133 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 break;
2135 case OFFLOAD_CMD_DRAIN:
2136 compress_drain(out->compr);
2137 send_callback = true;
2138 event = STREAM_CBK_EVENT_DRAIN_READY;
2139 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002140 case OFFLOAD_CMD_ERROR:
2141 send_callback = true;
2142 event = STREAM_CBK_EVENT_ERROR;
2143 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002144 default:
2145 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2146 break;
2147 }
Eric Laurenta1478072015-09-21 17:21:52 -07002148 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 out->offload_thread_blocked = false;
2150 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002151 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002152 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002154 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002155 free(cmd);
2156 }
2157
2158 pthread_cond_signal(&out->cond);
2159 while (!list_empty(&out->offload_cmd_list)) {
2160 item = list_head(&out->offload_cmd_list);
2161 list_remove(item);
2162 free(node_to_item(item, struct offload_cmd, node));
2163 }
2164 pthread_mutex_unlock(&out->lock);
2165
2166 return NULL;
2167}
2168
2169static int create_offload_callback_thread(struct stream_out *out)
2170{
2171 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2172 list_init(&out->offload_cmd_list);
2173 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2174 offload_thread_loop, out);
2175 return 0;
2176}
2177
2178static int destroy_offload_callback_thread(struct stream_out *out)
2179{
Eric Laurenta1478072015-09-21 17:21:52 -07002180 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 stop_compressed_output_l(out);
2182 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2183
2184 pthread_mutex_unlock(&out->lock);
2185 pthread_join(out->offload_thread, (void **) NULL);
2186 pthread_cond_destroy(&out->offload_cond);
2187
2188 return 0;
2189}
2190
Eric Laurent07eeafd2013-10-06 12:52:49 -07002191static bool allow_hdmi_channel_config(struct audio_device *adev)
2192{
2193 struct listnode *node;
2194 struct audio_usecase *usecase;
2195 bool ret = true;
2196
2197 list_for_each(node, &adev->usecase_list) {
2198 usecase = node_to_item(node, struct audio_usecase, list);
2199 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2200 /*
2201 * If voice call is already existing, do not proceed further to avoid
2202 * disabling/enabling both RX and TX devices, CSD calls, etc.
2203 * Once the voice call done, the HDMI channels can be configured to
2204 * max channels of remaining use cases.
2205 */
2206 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002207 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002208 __func__);
2209 ret = false;
2210 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002211 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2212 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002213 "no change in HDMI channels", __func__);
2214 ret = false;
2215 break;
2216 }
2217 }
2218 }
2219 return ret;
2220}
2221
2222static int check_and_set_hdmi_channels(struct audio_device *adev,
2223 unsigned int channels)
2224{
2225 struct listnode *node;
2226 struct audio_usecase *usecase;
2227
2228 /* Check if change in HDMI channel config is allowed */
2229 if (!allow_hdmi_channel_config(adev))
2230 return 0;
2231
2232 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002233 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002234 return 0;
2235 }
2236
2237 platform_set_hdmi_channels(adev->platform, channels);
2238 adev->cur_hdmi_channels = channels;
2239
2240 /*
2241 * Deroute all the playback streams routed to HDMI so that
2242 * the back end is deactivated. Note that backend will not
2243 * be deactivated if any one stream is connected to it.
2244 */
2245 list_for_each(node, &adev->usecase_list) {
2246 usecase = node_to_item(node, struct audio_usecase, list);
2247 if (usecase->type == PCM_PLAYBACK &&
2248 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002249 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002250 }
2251 }
2252
2253 /*
2254 * Enable all the streams disabled above. Now the HDMI backend
2255 * will be activated with new channel configuration
2256 */
2257 list_for_each(node, &adev->usecase_list) {
2258 usecase = node_to_item(node, struct audio_usecase, list);
2259 if (usecase->type == PCM_PLAYBACK &&
2260 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002261 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002262 }
2263 }
2264
2265 return 0;
2266}
2267
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002268static int check_and_set_usb_service_interval(struct audio_device *adev,
2269 struct audio_usecase *uc_info,
2270 bool min)
2271{
2272 struct listnode *node;
2273 struct audio_usecase *usecase;
2274 bool switch_usecases = false;
2275 bool reconfig = false;
2276
2277 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2278 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2279 return -1;
2280
2281 /* set if the valid usecase do not already exist */
2282 list_for_each(node, &adev->usecase_list) {
2283 usecase = node_to_item(node, struct audio_usecase, list);
2284 if (usecase->type == PCM_PLAYBACK &&
2285 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2286 switch (usecase->id) {
2287 case USECASE_AUDIO_PLAYBACK_MMAP:
2288 case USECASE_AUDIO_PLAYBACK_ULL:
2289 // cannot reconfig while mmap/ull is present.
2290 return -1;
2291 default:
2292 switch_usecases = true;
2293 break;
2294 }
2295 }
2296 if (switch_usecases)
2297 break;
2298 }
2299 /*
2300 * client can try to set service interval in start_output_stream
2301 * to min or to 0 (i.e reset) in stop_output_stream .
2302 */
2303 unsigned long service_interval =
2304 audio_extn_usb_find_service_interval(min, true /*playback*/);
2305 int ret = platform_set_usb_service_interval(adev->platform,
2306 true /*playback*/,
2307 service_interval,
2308 &reconfig);
2309 /* no change or not supported or no active usecases */
2310 if (ret || !reconfig || !switch_usecases)
2311 return -1;
2312 return 0;
2313#undef VALID_USECASE
2314}
2315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316static int stop_output_stream(struct stream_out *out)
2317{
2318 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 struct audio_usecase *uc_info;
2320 struct audio_device *adev = out->dev;
2321
Eric Laurent994a6932013-07-17 11:51:42 -07002322 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002323 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 uc_info = get_usecase_from_list(adev, out->usecase);
2325 if (uc_info == NULL) {
2326 ALOGE("%s: Could not find the usecase (%d) in the list",
2327 __func__, out->usecase);
2328 return -EINVAL;
2329 }
2330
Haynes Mathew George41f86652014-06-17 14:22:15 -07002331 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2332 if (adev->visualizer_stop_output != NULL)
2333 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2334 if (adev->offload_effects_stop_output != NULL)
2335 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002336 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2337 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2338 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002339 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002340
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002341 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2342 voice_set_device_mute_flag(adev, false);
2343
Eric Laurent150dbfe2013-02-27 14:31:02 -08002344 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002345 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002346
2347 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002348 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002350 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351
Eric Laurent0499d4f2014-08-25 22:39:29 -05002352 audio_extn_extspk_update(adev->extspk);
2353
Eric Laurent07eeafd2013-10-06 12:52:49 -07002354 /* Must be called after removing the usecase from list */
2355 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2356 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002357 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002358 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2359 if (ret == 0) {
2360 /* default service interval was successfully updated,
2361 reopen USB backend with new service interval */
2362 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2363 }
2364 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002365 }
juyuchend194b432018-11-16 14:15:16 +08002366 /* 1) media + voip output routing to handset must route media back to
2367 speaker when voip stops.
2368 2) trigger voip input to reroute when voip output changes to
2369 hearing aid. */
Robert Leec5271f72019-04-16 18:46:02 +08002370 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP ||
2371 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
HW Lee88512e92018-06-12 15:26:09 +08002372 struct listnode *node;
2373 struct audio_usecase *usecase;
2374 list_for_each(node, &adev->usecase_list) {
2375 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002376 if ((usecase->type == PCM_CAPTURE &&
2377 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2378 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002379 continue;
2380
2381 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2382 __func__, usecase->id, use_case_table[usecase->id],
2383 out->usecase, use_case_table[out->usecase]);
2384 select_devices(adev, usecase->id);
2385 }
2386 }
2387
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002388 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002389 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 return ret;
2391}
2392
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002393struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2394 unsigned int flags, unsigned int pcm_open_retry_count,
2395 struct pcm_config *config)
2396{
2397 struct pcm* pcm = NULL;
2398
2399 while (1) {
2400 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2401 if (pcm == NULL || !pcm_is_ready(pcm)) {
2402 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2403 if (pcm != NULL) {
2404 pcm_close(pcm);
2405 pcm = NULL;
2406 }
2407 if (pcm_open_retry_count-- == 0)
2408 return NULL;
2409
2410 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2411 continue;
2412 }
2413 break;
2414 }
2415
2416 if (pcm_is_ready(pcm)) {
2417 int ret = pcm_prepare(pcm);
2418 if (ret < 0) {
2419 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2420 pcm_close(pcm);
2421 pcm = NULL;
2422 }
2423 }
2424
2425 return pcm;
2426}
2427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428int start_output_stream(struct stream_out *out)
2429{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431 struct audio_usecase *uc_info;
2432 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002433 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002435 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2436 __func__, out->usecase, use_case_table[out->usecase],
2437 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2438 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002439
2440 if (out->card_status == CARD_STATUS_OFFLINE ||
2441 adev->card_status == CARD_STATUS_OFFLINE) {
2442 ALOGW("out->card_status or adev->card_status offline, try again");
2443 ret = -EAGAIN;
2444 goto error_config;
2445 }
2446
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002447 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2448 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002449 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002450 a2dp_combo = true;
2451 } else {
2452 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2453 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2454 ret = -EAGAIN;
2455 goto error_config;
2456 }
2457 }
2458 }
2459 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002460 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461 if (out->pcm_device_id < 0) {
2462 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2463 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002464 ret = -EINVAL;
2465 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002466 }
2467
2468 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2469 uc_info->id = out->usecase;
2470 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002471 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002472 uc_info->devices = out->devices;
2473 uc_info->in_snd_device = SND_DEVICE_NONE;
2474 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475
Eric Laurent07eeafd2013-10-06 12:52:49 -07002476 /* This must be called before adding this usecase to the list */
2477 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2478 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002479 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2480 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2481 /* USB backend is not reopened immediately.
2482 This is eventually done as part of select_devices */
2483 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002484
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002485 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486
Wei Wangf4837d52017-11-21 14:51:20 -08002487 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002488 audio_extn_perf_lock_acquire();
2489
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002490 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2491 (!audio_extn_a2dp_is_ready())) {
2492 if (!a2dp_combo) {
2493 check_a2dp_restore_l(adev, out, false);
2494 } else {
2495 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002496 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2497 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2498 else
2499 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002500 select_devices(adev, out->usecase);
2501 out->devices = dev;
2502 }
2503 } else {
2504 select_devices(adev, out->usecase);
2505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002506
Eric Laurent0499d4f2014-08-25 22:39:29 -05002507 audio_extn_extspk_update(adev->extspk);
2508
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002509 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2510 voice_set_device_mute_flag(adev, true);
2511
Andy Hung31aca912014-03-20 17:14:59 -07002512 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002513 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002514 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2515 out->pcm = NULL;
2516 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2517 COMPRESS_IN, &out->compr_config);
2518 if (out->compr && !is_compress_ready(out->compr)) {
2519 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2520 compress_close(out->compr);
2521 out->compr = NULL;
2522 ret = -EIO;
2523 goto error_open;
2524 }
2525 if (out->offload_callback)
2526 compress_nonblock(out->compr, out->non_blocking);
2527
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002528 if (adev->visualizer_start_output != NULL) {
2529 int capture_device_id =
2530 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2531 PCM_CAPTURE);
2532 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2533 adev->snd_card, capture_device_id);
2534 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002535 if (adev->offload_effects_start_output != NULL)
2536 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2537 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002538 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002539 ALOGE("%s: pcm stream not ready", __func__);
2540 goto error_open;
2541 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002542 ret = pcm_start(out->pcm);
2543 if (ret < 0) {
2544 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2545 goto error_open;
2546 }
2547 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002548 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002549 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002550
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002551 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2552 flags |= PCM_MMAP | PCM_NOIRQ;
2553 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002554 } else if (out->realtime) {
2555 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002556 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002557
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002558 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2559 flags, pcm_open_retry_count,
2560 &(out->config));
2561 if (out->pcm == NULL) {
2562 ret = -EIO;
2563 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002564 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002565
2566 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2567 if (adev->haptic_pcm != NULL) {
2568 pcm_close(adev->haptic_pcm);
2569 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002570 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002571 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2572 adev->haptic_pcm_device_id,
2573 flags, pcm_open_retry_count,
2574 &(adev->haptics_config));
2575 // failure to open haptics pcm shouldnt stop audio,
2576 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002577 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002578
Eric Laurent0e46adf2016-12-16 12:49:24 -08002579 if (out->realtime) {
2580 ret = pcm_start(out->pcm);
2581 if (ret < 0) {
2582 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2583 pcm_close(out->pcm);
2584 out->pcm = NULL;
2585 goto error_open;
2586 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002587 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002588 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002589
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002590 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002591 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002592 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002593 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002594
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002595 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2596 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2597 audio_low_latency_hint_start();
2598 }
2599
vivek mehtae59cfb22017-06-16 15:57:11 -07002600 // consider a scenario where on pause lower layers are tear down.
2601 // so on resume, swap mixer control need to be sent only when
2602 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002603 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002604
2605 platform_set_swap_channels(adev, true);
2606
Eric Laurent994a6932013-07-17 11:51:42 -07002607 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002608 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002610 if (adev->haptic_pcm) {
2611 pcm_close(adev->haptic_pcm);
2612 adev->haptic_pcm = NULL;
2613 }
Wei Wangf4837d52017-11-21 14:51:20 -08002614 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002615 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002617error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002618 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619}
2620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621static int check_input_parameters(uint32_t sample_rate,
2622 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002623 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002625 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2626 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002627 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2628 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002629 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2630 return -EINVAL;
2631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Eric Laurent74b55762017-07-09 17:04:53 -07002633 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2634 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002635 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002636 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002637 return -EINVAL;
2638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639
2640 switch (sample_rate) {
2641 case 8000:
2642 case 11025:
2643 case 12000:
2644 case 16000:
2645 case 22050:
2646 case 24000:
2647 case 32000:
2648 case 44100:
2649 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002650 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 break;
2652 default:
vivek mehtadae44712015-07-27 14:13:18 -07002653 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 return -EINVAL;
2655 }
2656
2657 return 0;
2658}
2659
Kevin Rocarda325aa22018-04-03 09:15:52 -07002660/** Add a value in a list if not already present.
2661 * @return true if value was successfully inserted or already present,
2662 * false if the list is full and does not contain the value.
2663 */
2664static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2665 for (size_t i = 0; i < list_length; i++) {
2666 if (list[i] == value) return true; // value is already present
2667 if (list[i] == 0) { // no values in this slot
2668 list[i] = value;
2669 return true; // value inserted
2670 }
2671 }
2672 return false; // could not insert value
2673}
2674
2675/** Add channel_mask in supported_channel_masks if not already present.
2676 * @return true if channel_mask was successfully inserted or already present,
2677 * false if supported_channel_masks is full and does not contain channel_mask.
2678 */
2679static void register_channel_mask(audio_channel_mask_t channel_mask,
2680 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2681 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2682 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2683}
2684
2685/** Add format in supported_formats if not already present.
2686 * @return true if format was successfully inserted or already present,
2687 * false if supported_formats is full and does not contain format.
2688 */
2689static void register_format(audio_format_t format,
2690 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2691 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2692 "%s: stream can not declare supporting its format %x", __func__, format);
2693}
2694/** Add sample_rate in supported_sample_rates if not already present.
2695 * @return true if sample_rate was successfully inserted or already present,
2696 * false if supported_sample_rates is full and does not contain sample_rate.
2697 */
2698static void register_sample_rate(uint32_t sample_rate,
2699 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2700 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2701 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2702}
2703
vivek mehtaa68fea62017-06-08 19:04:02 -07002704static size_t get_stream_buffer_size(size_t duration_ms,
2705 uint32_t sample_rate,
2706 audio_format_t format,
2707 int channel_count,
2708 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709{
2710 size_t size = 0;
2711
vivek mehtaa68fea62017-06-08 19:04:02 -07002712 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002713 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002714 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002715
2716 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717
Glenn Kasten4f993392014-05-14 07:30:48 -07002718 /* make sure the size is multiple of 32 bytes
2719 * At 48 kHz mono 16-bit PCM:
2720 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2721 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2722 */
2723 size += 0x1f;
2724 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002725
2726 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727}
2728
2729static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734}
2735
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002736static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737{
2738 return -ENOSYS;
2739}
2740
2741static size_t out_get_buffer_size(const struct audio_stream *stream)
2742{
2743 struct stream_out *out = (struct stream_out *)stream;
2744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2746 return out->compr_config.fragment_size;
2747 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002748 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002749 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750}
2751
2752static uint32_t out_get_channels(const struct audio_stream *stream)
2753{
2754 struct stream_out *out = (struct stream_out *)stream;
2755
2756 return out->channel_mask;
2757}
2758
2759static audio_format_t out_get_format(const struct audio_stream *stream)
2760{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 struct stream_out *out = (struct stream_out *)stream;
2762
2763 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764}
2765
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002766static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767{
2768 return -ENOSYS;
2769}
2770
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002771/* must be called with out->lock locked */
2772static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773{
2774 struct stream_out *out = (struct stream_out *)stream;
2775 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002776 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002779 if (adev->adm_deregister_stream)
2780 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002781 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002782 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2784 if (out->pcm) {
2785 pcm_close(out->pcm);
2786 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002787
2788 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2789 if (adev->haptic_pcm) {
2790 pcm_close(adev->haptic_pcm);
2791 adev->haptic_pcm = NULL;
2792 }
2793
2794 if (adev->haptic_buffer != NULL) {
2795 free(adev->haptic_buffer);
2796 adev->haptic_buffer = NULL;
2797 adev->haptic_buffer_size = 0;
2798 }
2799 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002801 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002802 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002803 out->playback_started = false;
2804 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 } else {
2806 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002807 out->gapless_mdata.encoder_delay = 0;
2808 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 if (out->compr != NULL) {
2810 compress_close(out->compr);
2811 out->compr = NULL;
2812 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002813 }
Phil Burkbc991042017-02-24 08:06:44 -08002814 if (do_stop) {
2815 stop_output_stream(out);
2816 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002817 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002819 return 0;
2820}
2821
2822static int out_standby(struct audio_stream *stream)
2823{
2824 struct stream_out *out = (struct stream_out *)stream;
2825
2826 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2827 out->usecase, use_case_table[out->usecase]);
2828
2829 lock_output_stream(out);
2830 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002832 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 return 0;
2834}
2835
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002836static int out_on_error(struct audio_stream *stream)
2837{
2838 struct stream_out *out = (struct stream_out *)stream;
2839 struct audio_device *adev = out->dev;
2840 bool do_standby = false;
2841
2842 lock_output_stream(out);
2843 if (!out->standby) {
2844 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2845 stop_compressed_output_l(out);
2846 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2847 } else
2848 do_standby = true;
2849 }
2850 pthread_mutex_unlock(&out->lock);
2851
2852 if (do_standby)
2853 return out_standby(&out->stream.common);
2854
2855 return 0;
2856}
2857
Andy Hung7401c7c2016-09-21 12:41:21 -07002858static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859{
Andy Hung7401c7c2016-09-21 12:41:21 -07002860 struct stream_out *out = (struct stream_out *)stream;
2861
2862 // We try to get the lock for consistency,
2863 // but it isn't necessary for these variables.
2864 // If we're not in standby, we may be blocked on a write.
2865 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2866 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2867 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2868
Andy Hung572633e2019-02-19 11:58:24 -08002869 char buffer[256]; // for statistics formatting
2870 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2871 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2872
Andy Hung241e36f2019-02-19 12:00:38 -08002873 if (out->start_latency_ms.n > 0) {
2874 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2875 dprintf(fd, " Start latency ms: %s\n", buffer);
2876 }
2877
Andy Hung7401c7c2016-09-21 12:41:21 -07002878 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002879 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002880 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002881
2882 // dump error info
2883 (void)error_log_dump(
2884 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 return 0;
2887}
2888
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002889static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2890{
2891 int ret = 0;
2892 char value[32];
2893 struct compr_gapless_mdata tmp_mdata;
2894
2895 if (!out || !parms) {
2896 return -EINVAL;
2897 }
2898
2899 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2900 if (ret >= 0) {
2901 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2902 } else {
2903 return -EINVAL;
2904 }
2905
2906 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2907 if (ret >= 0) {
2908 tmp_mdata.encoder_padding = atoi(value);
2909 } else {
2910 return -EINVAL;
2911 }
2912
2913 out->gapless_mdata = tmp_mdata;
2914 out->send_new_metadata = 1;
2915 ALOGV("%s new encoder delay %u and padding %u", __func__,
2916 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2917
2918 return 0;
2919}
2920
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002921static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2922{
2923 return out == adev->primary_output || out == adev->voice_tx_output;
2924}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002925
Kevin Rocard1e02c882017-08-09 15:26:07 -07002926static int get_alive_usb_card(struct str_parms* parms) {
2927 int card;
2928 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2929 !audio_extn_usb_alive(card)) {
2930 return card;
2931 }
2932 return -ENODEV;
2933}
2934
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2936{
2937 struct stream_out *out = (struct stream_out *)stream;
2938 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002939 struct audio_usecase *usecase;
2940 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 struct str_parms *parms;
2942 char value[32];
2943 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002944 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002945 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002946 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947
Eric Laurent2e140aa2016-06-30 17:14:46 -07002948 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002949 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950 parms = str_parms_create_str(kvpairs);
2951 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2952 if (ret >= 0) {
2953 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002954
Eric Laurenta1478072015-09-21 17:21:52 -07002955 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002956
2957 // The usb driver needs to be closed after usb device disconnection
2958 // otherwise audio is no longer played on the new usb devices.
2959 // By forcing the stream in standby, the usb stack refcount drops to 0
2960 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002961 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002962 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002963 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2964 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2965 out_standby_l(&out->stream.common);
2966 }
2967 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002968 }
2969
Eric Laurent150dbfe2013-02-27 14:31:02 -08002970 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002972 /*
2973 * When HDMI cable is unplugged the music playback is paused and
2974 * the policy manager sends routing=0. But the audioflinger
2975 * continues to write data until standby time (3sec).
2976 * As the HDMI core is turned off, the write gets blocked.
2977 * Avoid this by routing audio to speaker until standby.
2978 */
2979 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2980 val == AUDIO_DEVICE_NONE) {
2981 val = AUDIO_DEVICE_OUT_SPEAKER;
2982 }
2983
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002984 /*
2985 * When A2DP is disconnected the
2986 * music playback is paused and the policy manager sends routing=0
2987 * But the audioflingercontinues to write data until standby time
2988 * (3sec). As BT is turned off, the write gets blocked.
2989 * Avoid this by routing audio to speaker until standby.
2990 */
2991 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2992 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07002993 !audio_extn_a2dp_is_ready() &&
2994 !adev->bt_sco_on) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002995 val = AUDIO_DEVICE_OUT_SPEAKER;
2996 }
2997
2998 /* To avoid a2dp to sco overlapping / BT device improper state
2999 * check with BT lib about a2dp streaming support before routing
3000 */
3001 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
3002 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08003003 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003004 //combo usecase just by pass a2dp
3005 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
3006 bypass_a2dp = true;
3007 } else {
3008 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
3009 /* update device to a2dp and don't route as BT returned error
3010 * However it is still possible a2dp routing called because
3011 * of current active device disconnection (like wired headset)
3012 */
3013 out->devices = val;
3014 pthread_mutex_unlock(&out->lock);
3015 pthread_mutex_unlock(&adev->lock);
3016 status = -ENOSYS;
3017 goto routing_fail;
3018 }
3019 }
3020 }
3021
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003022 audio_devices_t new_dev = val;
3023
3024 // Workaround: If routing to an non existing usb device, fail gracefully
3025 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003026 int card;
3027 if (audio_is_usb_out_device(new_dev) &&
3028 (card = get_alive_usb_card(parms)) >= 0) {
3029
3030 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003031 pthread_mutex_unlock(&adev->lock);
3032 pthread_mutex_unlock(&out->lock);
3033 status = -ENOSYS;
3034 goto routing_fail;
3035 }
3036
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003037 /*
3038 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07003039 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003040 * the select_devices(). But how do we undo this?
3041 *
3042 * For example, music playback is active on headset (deep-buffer usecase)
3043 * and if we go to ringtones and select a ringtone, low-latency usecase
3044 * will be started on headset+speaker. As we can't enable headset+speaker
3045 * and headset devices at the same time, select_devices() switches the music
3046 * playback to headset+speaker while starting low-lateny usecase for ringtone.
3047 * So when the ringtone playback is completed, how do we undo the same?
3048 *
3049 * We are relying on the out_set_parameters() call on deep-buffer output,
3050 * once the ringtone playback is ended.
3051 * NOTE: We should not check if the current devices are same as new devices.
3052 * Because select_devices() must be called to switch back the music
3053 * playback to headset.
3054 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003055 if (new_dev != AUDIO_DEVICE_NONE) {
3056 bool same_dev = out->devices == new_dev;
3057 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003058
Eric Laurenta7657192014-10-09 21:09:33 -07003059 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08003060 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07003061 if (adev->mode == AUDIO_MODE_IN_CALL) {
3062 adev->current_call_output = out;
3063 ret = voice_start_call(adev);
3064 }
3065 } else {
3066 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003067 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07003068 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003069 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003070
3071 if (!out->standby) {
3072 if (!same_dev) {
3073 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003074 // inform adm before actual routing to prevent glitches.
3075 if (adev->adm_on_routing_change) {
3076 adev->adm_on_routing_change(adev->adm_data,
3077 out->handle);
3078 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003079 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003080 if (!bypass_a2dp) {
3081 select_devices(adev, out->usecase);
3082 } else {
juyuchen9baad392018-06-05 19:02:10 +08003083 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3084 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3085 else
3086 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003087 select_devices(adev, out->usecase);
3088 out->devices = new_dev;
3089 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08003090 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07003091
3092 // on device switch force swap, lower functions will make sure
3093 // to check if swap is allowed or not.
3094
3095 if (!same_dev)
3096 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003097
3098 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3099 out->a2dp_compress_mute &&
3100 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
3101 pthread_mutex_lock(&out->compr_mute_lock);
3102 out->a2dp_compress_mute = false;
3103 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
3104 pthread_mutex_unlock(&out->compr_mute_lock);
3105 }
vivek mehta0d3637a2016-07-24 09:32:02 -07003106 }
3107
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003108 }
3109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003111 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003112
3113 /*handles device and call state changes*/
3114 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003116 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003117
3118 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3119 parse_compress_metadata(out, parms);
3120 }
3121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003123 ALOGV("%s: exit: code(%d)", __func__, status);
3124 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125}
3126
Haynes Mathew George569b7482017-05-08 14:44:27 -07003127static bool stream_get_parameter_channels(struct str_parms *query,
3128 struct str_parms *reply,
3129 audio_channel_mask_t *supported_channel_masks) {
3130 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003131 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003133 size_t i, j;
3134
3135 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3136 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 value[0] = '\0';
3138 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003139 while (supported_channel_masks[i] != 0) {
3140 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3141 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 if (!first) {
3143 strcat(value, "|");
3144 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003145 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146 first = false;
3147 break;
3148 }
3149 }
3150 i++;
3151 }
3152 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003153 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003154 return ret >= 0;
3155}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003156
Haynes Mathew George569b7482017-05-08 14:44:27 -07003157static bool stream_get_parameter_formats(struct str_parms *query,
3158 struct str_parms *reply,
3159 audio_format_t *supported_formats) {
3160 int ret = -1;
3161 char value[256];
3162 int i;
3163
3164 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3165 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003166 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003167 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003168 case AUDIO_FORMAT_PCM_16_BIT:
3169 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3170 break;
3171 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3172 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3173 break;
3174 case AUDIO_FORMAT_PCM_32_BIT:
3175 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3176 break;
3177 default:
3178 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003179 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003180 break;
3181 }
3182 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003183 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003184 return ret >= 0;
3185}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003186
Haynes Mathew George569b7482017-05-08 14:44:27 -07003187static bool stream_get_parameter_rates(struct str_parms *query,
3188 struct str_parms *reply,
3189 uint32_t *supported_sample_rates) {
3190
3191 int i;
3192 char value[256];
3193 int ret = -1;
3194 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3195 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003196 value[0] = '\0';
3197 i=0;
3198 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003199 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003200 int avail = sizeof(value) - cursor;
3201 ret = snprintf(value + cursor, avail, "%s%d",
3202 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003203 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003204 if (ret < 0 || ret >= avail) {
3205 // if cursor is at the last element of the array
3206 // overwrite with \0 is duplicate work as
3207 // snprintf already put a \0 in place.
3208 // else
3209 // we had space to write the '|' at value[cursor]
3210 // (which will be overwritten) or no space to fill
3211 // the first element (=> cursor == 0)
3212 value[cursor] = '\0';
3213 break;
3214 }
3215 cursor += ret;
3216 ++i;
3217 }
3218 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3219 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003220 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003221 return ret >= 0;
3222}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003223
Haynes Mathew George569b7482017-05-08 14:44:27 -07003224static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3225{
3226 struct stream_out *out = (struct stream_out *)stream;
3227 struct str_parms *query = str_parms_create_str(keys);
3228 char *str;
3229 struct str_parms *reply = str_parms_create();
3230 bool replied = false;
3231 ALOGV("%s: enter: keys - %s", __func__, keys);
3232
3233 replied |= stream_get_parameter_channels(query, reply,
3234 &out->supported_channel_masks[0]);
3235 replied |= stream_get_parameter_formats(query, reply,
3236 &out->supported_formats[0]);
3237 replied |= stream_get_parameter_rates(query, reply,
3238 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003239 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 str = str_parms_to_str(reply);
3241 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003242 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 }
3244 str_parms_destroy(query);
3245 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003246 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 return str;
3248}
3249
3250static uint32_t out_get_latency(const struct audio_stream_out *stream)
3251{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003252 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003254 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3257 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003258 else if ((out->realtime) ||
3259 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003260 // since the buffer won't be filled up faster than realtime,
3261 // return a smaller number
3262 period_ms = (out->af_period_multiplier * out->config.period_size *
3263 1000) / (out->config.rate);
3264 hw_delay = platform_render_latency(out->usecase)/1000;
3265 return period_ms + hw_delay;
3266 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003268 latency = (out->config.period_count * out->config.period_size * 1000) /
3269 (out->config.rate);
3270
3271 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3272 latency += audio_extn_a2dp_get_encoder_latency();
3273
3274 return latency;
3275}
3276
3277static int set_compr_volume(struct audio_stream_out *stream, float left,
3278 float right)
3279{
3280 struct stream_out *out = (struct stream_out *)stream;
3281 int volume[2];
3282 char mixer_ctl_name[128];
3283 struct audio_device *adev = out->dev;
3284 struct mixer_ctl *ctl;
3285 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3286 PCM_PLAYBACK);
3287
3288 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3289 "Compress Playback %d Volume", pcm_device_id);
3290 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3291 if (!ctl) {
3292 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3293 __func__, mixer_ctl_name);
3294 return -EINVAL;
3295 }
3296 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3297 __func__, mixer_ctl_name, left, right);
3298 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3299 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3300 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3301
3302 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303}
3304
3305static int out_set_volume(struct audio_stream_out *stream, float left,
3306 float right)
3307{
Eric Laurenta9024de2013-04-04 09:19:12 -07003308 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003309 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003310
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003311 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003312 /* only take left channel into account: the API is for stereo anyway */
3313 out->muted = (left == 0.0f);
3314 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003315 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003316 pthread_mutex_lock(&out->compr_mute_lock);
3317 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3318 if (!out->a2dp_compress_mute)
3319 ret = set_compr_volume(stream, left, right);
3320 out->volume_l = left;
3321 out->volume_r = right;
3322 pthread_mutex_unlock(&out->compr_mute_lock);
3323 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003324 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003325 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3326 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3327 if (!out->standby) {
3328 // if in standby, cached volume will be sent after stream is opened
3329 audio_extn_utils_send_app_type_gain(out->dev,
3330 out->app_type_cfg.app_type,
3331 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003332 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003333 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003334 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 return -ENOSYS;
3337}
3338
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003339// note: this call is safe only if the stream_cb is
3340// removed first in close_output_stream (as is done now).
3341static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3342{
3343 if (!stream || !parms)
3344 return;
3345
3346 struct stream_out *out = (struct stream_out *)stream;
3347 struct audio_device *adev = out->dev;
3348
3349 card_status_t status;
3350 int card;
3351 if (parse_snd_card_status(parms, &card, &status) < 0)
3352 return;
3353
3354 pthread_mutex_lock(&adev->lock);
3355 bool valid_cb = (card == adev->snd_card);
3356 pthread_mutex_unlock(&adev->lock);
3357
3358 if (!valid_cb)
3359 return;
3360
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003361 lock_output_stream(out);
3362 if (out->card_status != status)
3363 out->card_status = status;
3364 pthread_mutex_unlock(&out->lock);
3365
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003366 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3367 use_case_table[out->usecase],
3368 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3369
3370 if (status == CARD_STATUS_OFFLINE)
3371 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003372
3373 return;
3374}
3375
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003376#ifdef NO_AUDIO_OUT
3377static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003378 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003379{
3380 struct stream_out *out = (struct stream_out *)stream;
3381
3382 /* No Output device supported other than BT for playback.
3383 * Sleep for the amount of buffer duration
3384 */
Eric Laurenta1478072015-09-21 17:21:52 -07003385 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003386 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3387 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003388 out_get_sample_rate(&out->stream.common));
3389 pthread_mutex_unlock(&out->lock);
3390 return bytes;
3391}
3392#endif
3393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3395 size_t bytes)
3396{
3397 struct stream_out *out = (struct stream_out *)stream;
3398 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003399 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003400 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401
Eric Laurenta1478072015-09-21 17:21:52 -07003402 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003403 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003404 const size_t frame_size = audio_stream_out_frame_size(stream);
3405 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003406
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3408 error_code = ERROR_CODE_WRITE;
3409 goto exit;
3410 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003411
3412 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3413 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003414 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003415 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3416 ret = -EIO;
3417 goto exit;
3418 }
3419 }
3420 }
3421
Andy Hung572633e2019-02-19 11:58:24 -08003422 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003424 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003425 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3426
Eric Laurent150dbfe2013-02-27 14:31:02 -08003427 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003429
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003432 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003433 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 goto exit;
3435 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003436
vivek mehta40125092017-08-21 18:48:51 -07003437 // after standby always force set last known cal step
3438 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3439 ALOGD("%s: retry previous failed cal level set", __func__);
3440 send_gain_dep_calibration_l();
3441 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003442
Andy Hung241e36f2019-02-19 12:00:38 -08003443 // log startup time in ms.
3444 simple_stats_log(
3445 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003446 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003449 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003450 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003451 if (out->send_new_metadata) {
3452 ALOGVV("send new gapless metadata");
3453 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3454 out->send_new_metadata = 0;
3455 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003456 unsigned int avail;
3457 struct timespec tstamp;
3458 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3459 /* Do not limit write size if the available frames count is unknown */
3460 if (ret != 0) {
3461 avail = bytes;
3462 }
3463 if (avail == 0) {
3464 ret = 0;
3465 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003466 // check for compressed format underrun, essentially an empty buffer check
3467 // for a lack of better measurement.
3468 if (!was_in_standby && avail == out->kernel_buffer_size) {
3469 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3470 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3471 }
3472
Eric Laurentb49b3f62016-02-29 17:59:49 -08003473 if (avail > bytes) {
3474 avail = bytes;
3475 }
3476 ret = compress_write(out->compr, buffer, avail);
3477 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3478 __func__, avail, ret);
3479 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003480
Eric Laurent6e895242013-09-05 16:10:57 -07003481 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3483 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003484 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 compress_start(out->compr);
3486 out->playback_started = 1;
3487 out->offload_state = OFFLOAD_STATE_PLAYING;
3488 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003489 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003490 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003491 } else {
3492 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003493 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003494 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003495 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496 return ret;
3497 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003498 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003500 size_t bytes_to_write = bytes;
3501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003502 if (out->muted)
3503 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003504 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003505 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003506 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3507 int16_t *src = (int16_t *)buffer;
3508 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003509
Eric Laurentad2dde92017-09-20 18:27:31 -07003510 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3511 out->format != AUDIO_FORMAT_PCM_16_BIT,
3512 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003513
Eric Laurentad2dde92017-09-20 18:27:31 -07003514 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3515 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3516 }
3517 bytes_to_write /= 2;
3518 }
Andy Hung572633e2019-02-19 11:58:24 -08003519
3520 // Note: since out_get_presentation_position() is called alternating with out_write()
3521 // by AudioFlinger, we can check underruns using the prior timestamp read.
3522 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3523 if (out->last_fifo_valid) {
3524 // compute drain to see if there is an underrun.
3525 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3526 const int64_t frames_by_time =
3527 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3528 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3529
3530 if (underrun > 0) {
3531 simple_stats_log(&out->fifo_underruns, underrun);
3532
3533 ALOGW("%s: underrun(%lld) "
3534 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3535 __func__,
3536 (long long)out->fifo_underruns.n,
3537 (long long)frames_by_time,
3538 (long long)out->last_fifo_frames_remaining);
3539 }
3540 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3541 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003542
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003543 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003544 request_out_focus(out, ns);
3545
3546 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003547 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003548 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003549 } else {
3550 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3551 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3552 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3553 size_t frame_size = channel_count * bytes_per_sample;
3554 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003555
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003556 bool force_haptic_path =
3557 property_get_bool("vendor.audio.test_haptic", false);
3558
3559 // extract Haptics data from Audio buffer
3560 bool alloc_haptic_buffer = false;
3561 int haptic_channel_count = adev->haptics_config.channels;
3562 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3563 size_t audio_frame_size = frame_size - haptic_frame_size;
3564 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3565
3566 if (adev->haptic_buffer == NULL) {
3567 alloc_haptic_buffer = true;
3568 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3569 free(adev->haptic_buffer);
3570 adev->haptic_buffer_size = 0;
3571 alloc_haptic_buffer = true;
3572 }
3573
3574 if (alloc_haptic_buffer) {
3575 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3576 adev->haptic_buffer_size = total_haptic_buffer_size;
3577 }
3578
3579 size_t src_index = 0, aud_index = 0, hap_index = 0;
3580 uint8_t *audio_buffer = (uint8_t *)buffer;
3581 uint8_t *haptic_buffer = adev->haptic_buffer;
3582
3583 // This is required for testing only. This works for stereo data only.
3584 // One channel is fed to audio stream and other to haptic stream for testing.
3585 if (force_haptic_path) {
3586 audio_frame_size = haptic_frame_size = bytes_per_sample;
3587 }
3588
3589 for (size_t i = 0; i < frame_count; i++) {
3590 for (size_t j = 0; j < audio_frame_size; j++)
3591 audio_buffer[aud_index++] = audio_buffer[src_index++];
3592
3593 for (size_t j = 0; j < haptic_frame_size; j++)
3594 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3595 }
3596
3597 // This is required for testing only.
3598 // Discard haptic channel data.
3599 if (force_haptic_path) {
3600 src_index += haptic_frame_size;
3601 }
3602
3603 // write to audio pipeline
3604 ret = pcm_write(out->pcm,
3605 (void *)audio_buffer,
3606 frame_count * audio_frame_size);
3607
3608 // write to haptics pipeline
3609 if (adev->haptic_pcm)
3610 ret = pcm_write(adev->haptic_pcm,
3611 (void *)adev->haptic_buffer,
3612 frame_count * haptic_frame_size);
3613
3614 } else {
3615 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3616 }
3617 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003618 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003619 } else {
3620 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003622 }
3623
3624exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003625 // For PCM we always consume the buffer and return #bytes regardless of ret.
3626 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003627 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003628 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003629 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003630
Andy Hung7401c7c2016-09-21 12:41:21 -07003631 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003632 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003633 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3634 ALOGE_IF(out->pcm != NULL,
3635 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003636 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003637 // usleep not guaranteed for values over 1 second but we don't limit here.
3638 }
3639 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 pthread_mutex_unlock(&out->lock);
3642
3643 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003644 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003645 if (sleeptime_us != 0)
3646 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003647 }
3648 return bytes;
3649}
3650
3651static int out_get_render_position(const struct audio_stream_out *stream,
3652 uint32_t *dsp_frames)
3653{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003654 struct stream_out *out = (struct stream_out *)stream;
3655 *dsp_frames = 0;
3656 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003657 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003658 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003659 unsigned long frames = 0;
3660 // TODO: check return value
3661 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3662 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 ALOGVV("%s rendered frames %d sample_rate %d",
3664 __func__, *dsp_frames, out->sample_rate);
3665 }
3666 pthread_mutex_unlock(&out->lock);
3667 return 0;
3668 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003669 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670}
3671
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003672static int out_add_audio_effect(const struct audio_stream *stream __unused,
3673 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674{
3675 return 0;
3676}
3677
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003678static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3679 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680{
3681 return 0;
3682}
3683
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003684static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3685 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003687 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688}
3689
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003690static int out_get_presentation_position(const struct audio_stream_out *stream,
3691 uint64_t *frames, struct timespec *timestamp)
3692{
3693 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003694 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003695 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003696
Eric Laurenta1478072015-09-21 17:21:52 -07003697 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003698
Eric Laurent949a0892013-09-20 09:20:13 -07003699 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3700 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003701 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003702 compress_get_tstamp(out->compr, &dsp_frames,
3703 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003704 // Adjustment accounts for A2DP encoder latency with offload usecases
3705 // Note: Encoder latency is returned in ms.
3706 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3707 unsigned long offset =
3708 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3709 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3710 }
Eric Laurent949a0892013-09-20 09:20:13 -07003711 ALOGVV("%s rendered frames %ld sample_rate %d",
3712 __func__, dsp_frames, out->sample_rate);
3713 *frames = dsp_frames;
3714 ret = 0;
3715 /* this is the best we can do */
3716 clock_gettime(CLOCK_MONOTONIC, timestamp);
3717 }
3718 } else {
3719 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003720 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003721 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003722
3723 // pcm_get_htimestamp() computes the available frames by comparing
3724 // the alsa driver hw_ptr and the appl_ptr levels.
3725 // In underrun, the hw_ptr may keep running and report an excessively
3726 // large number available number.
3727 if (avail > out->kernel_buffer_size) {
3728 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3729 __func__, avail, out->kernel_buffer_size);
3730 avail = out->kernel_buffer_size;
3731 out->last_fifo_frames_remaining = 0;
3732 } else {
3733 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3734 }
3735 out->last_fifo_valid = true;
3736 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3737
3738 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3739
3740 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3741 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3742
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003743 // This adjustment accounts for buffering after app processor.
3744 // It is based on estimated DSP latency per use case, rather than exact.
3745 signed_frames -=
3746 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3747
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003748 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3749 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3750 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3751 signed_frames -=
3752 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3753 }
3754
Eric Laurent949a0892013-09-20 09:20:13 -07003755 // It would be unusual for this value to be negative, but check just in case ...
3756 if (signed_frames >= 0) {
3757 *frames = signed_frames;
3758 ret = 0;
3759 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003760 }
3761 }
3762 }
3763
3764 pthread_mutex_unlock(&out->lock);
3765
3766 return ret;
3767}
3768
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003769static int out_set_callback(struct audio_stream_out *stream,
3770 stream_callback_t callback, void *cookie)
3771{
3772 struct stream_out *out = (struct stream_out *)stream;
3773
3774 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003775 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003776 out->offload_callback = callback;
3777 out->offload_cookie = cookie;
3778 pthread_mutex_unlock(&out->lock);
3779 return 0;
3780}
3781
3782static int out_pause(struct audio_stream_out* stream)
3783{
3784 struct stream_out *out = (struct stream_out *)stream;
3785 int status = -ENOSYS;
3786 ALOGV("%s", __func__);
3787 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003788 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3790 status = compress_pause(out->compr);
3791 out->offload_state = OFFLOAD_STATE_PAUSED;
3792 }
3793 pthread_mutex_unlock(&out->lock);
3794 }
3795 return status;
3796}
3797
3798static int out_resume(struct audio_stream_out* stream)
3799{
3800 struct stream_out *out = (struct stream_out *)stream;
3801 int status = -ENOSYS;
3802 ALOGV("%s", __func__);
3803 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3804 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003805 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3807 status = compress_resume(out->compr);
3808 out->offload_state = OFFLOAD_STATE_PLAYING;
3809 }
3810 pthread_mutex_unlock(&out->lock);
3811 }
3812 return status;
3813}
3814
3815static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3816{
3817 struct stream_out *out = (struct stream_out *)stream;
3818 int status = -ENOSYS;
3819 ALOGV("%s", __func__);
3820 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003821 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3823 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3824 else
3825 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3826 pthread_mutex_unlock(&out->lock);
3827 }
3828 return status;
3829}
3830
3831static int out_flush(struct audio_stream_out* stream)
3832{
3833 struct stream_out *out = (struct stream_out *)stream;
3834 ALOGV("%s", __func__);
3835 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003836 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003837 stop_compressed_output_l(out);
3838 pthread_mutex_unlock(&out->lock);
3839 return 0;
3840 }
3841 return -ENOSYS;
3842}
3843
Eric Laurent0e46adf2016-12-16 12:49:24 -08003844static int out_stop(const struct audio_stream_out* stream)
3845{
3846 struct stream_out *out = (struct stream_out *)stream;
3847 struct audio_device *adev = out->dev;
3848 int ret = -ENOSYS;
3849
3850 ALOGV("%s", __func__);
3851 pthread_mutex_lock(&adev->lock);
3852 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3853 out->playback_started && out->pcm != NULL) {
3854 pcm_stop(out->pcm);
3855 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003856 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003857 }
3858 pthread_mutex_unlock(&adev->lock);
3859 return ret;
3860}
3861
3862static int out_start(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 ret = start_output_stream(out);
3873 if (ret == 0) {
3874 out->playback_started = true;
3875 }
3876 }
3877 pthread_mutex_unlock(&adev->lock);
3878 return ret;
3879}
3880
Phil Burkbc991042017-02-24 08:06:44 -08003881/*
3882 * Modify config->period_count based on min_size_frames
3883 */
3884static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3885{
3886 int periodCountRequested = (min_size_frames + config->period_size - 1)
3887 / config->period_size;
3888 int periodCount = MMAP_PERIOD_COUNT_MIN;
3889
3890 ALOGV("%s original config.period_size = %d config.period_count = %d",
3891 __func__, config->period_size, config->period_count);
3892
3893 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3894 periodCount *= 2;
3895 }
3896 config->period_count = periodCount;
3897
3898 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3899}
3900
Phil Burk51e6bc42019-03-25 10:23:35 -07003901// Read offset for the positional timestamp from a persistent vendor property.
3902// This is to workaround apparent inaccuracies in the timing information that
3903// is used by the AAudio timing model. The inaccuracies can cause glitches.
3904static int64_t get_mmap_out_time_offset() {
3905 const int32_t kDefaultOffsetMicros = 0;
3906 int32_t mmap_time_offset_micros = property_get_int32(
3907 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3908 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3909 return mmap_time_offset_micros * (int64_t)1000;
3910}
3911
Eric Laurent0e46adf2016-12-16 12:49:24 -08003912static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3913 int32_t min_size_frames,
3914 struct audio_mmap_buffer_info *info)
3915{
3916 struct stream_out *out = (struct stream_out *)stream;
3917 struct audio_device *adev = out->dev;
3918 int ret = 0;
3919 unsigned int offset1;
3920 unsigned int frames1;
3921 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003922 uint32_t mmap_size;
3923 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003924
3925 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003926 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003927 pthread_mutex_lock(&adev->lock);
3928
3929 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003930 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003931 ret = -EINVAL;
3932 goto exit;
3933 }
3934 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003935 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003936 ret = -ENOSYS;
3937 goto exit;
3938 }
3939 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3940 if (out->pcm_device_id < 0) {
3941 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3942 __func__, out->pcm_device_id, out->usecase);
3943 ret = -EINVAL;
3944 goto exit;
3945 }
Phil Burkbc991042017-02-24 08:06:44 -08003946
3947 adjust_mmap_period_count(&out->config, min_size_frames);
3948
Eric Laurent0e46adf2016-12-16 12:49:24 -08003949 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3950 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3951 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3952 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3953 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3954 step = "open";
3955 ret = -ENODEV;
3956 goto exit;
3957 }
3958 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3959 if (ret < 0) {
3960 step = "begin";
3961 goto exit;
3962 }
3963 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003964 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003965 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003966 ret = platform_get_mmap_data_fd(adev->platform,
3967 out->pcm_device_id, 0 /*playback*/,
3968 &info->shared_memory_fd,
3969 &mmap_size);
3970 if (ret < 0) {
3971 // Fall back to non exclusive mode
3972 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3973 } else {
3974 if (mmap_size < buffer_size) {
3975 step = "mmap";
3976 goto exit;
3977 }
3978 // FIXME: indicate exclusive mode support by returning a negative buffer size
3979 info->buffer_size_frames *= -1;
3980 }
3981 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003982
3983 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3984 if (ret < 0) {
3985 step = "commit";
3986 goto exit;
3987 }
Phil Burkbc991042017-02-24 08:06:44 -08003988
Phil Burk51e6bc42019-03-25 10:23:35 -07003989 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
3990
Phil Burkbc991042017-02-24 08:06:44 -08003991 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003992 ret = 0;
3993
3994 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3995 __func__, info->shared_memory_address, info->buffer_size_frames);
3996
3997exit:
3998 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003999 if (out->pcm == NULL) {
4000 ALOGE("%s: %s - %d", __func__, step, ret);
4001 } else {
4002 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004003 pcm_close(out->pcm);
4004 out->pcm = NULL;
4005 }
4006 }
4007 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004008 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004009 return ret;
4010}
4011
4012static int out_get_mmap_position(const struct audio_stream_out *stream,
4013 struct audio_mmap_position *position)
4014{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004015 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004016 struct stream_out *out = (struct stream_out *)stream;
4017 ALOGVV("%s", __func__);
4018 if (position == NULL) {
4019 return -EINVAL;
4020 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004021 lock_output_stream(out);
4022 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
4023 out->pcm == NULL) {
4024 ret = -ENOSYS;
4025 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004026 }
4027
4028 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004029 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004030 if (ret < 0) {
4031 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004032 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004033 }
Phil Burk51e6bc42019-03-25 10:23:35 -07004034 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4035 + out->mmap_time_offset_nanos;
4036
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004037exit:
4038 pthread_mutex_unlock(&out->lock);
4039 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004040}
4041
4042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043/** audio_stream_in implementation **/
4044static uint32_t in_get_sample_rate(const struct audio_stream *stream)
4045{
4046 struct stream_in *in = (struct stream_in *)stream;
4047
4048 return in->config.rate;
4049}
4050
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004051static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052{
4053 return -ENOSYS;
4054}
4055
4056static size_t in_get_buffer_size(const struct audio_stream *stream)
4057{
4058 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004059 return in->config.period_size * in->af_period_multiplier *
4060 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061}
4062
4063static uint32_t in_get_channels(const struct audio_stream *stream)
4064{
4065 struct stream_in *in = (struct stream_in *)stream;
4066
4067 return in->channel_mask;
4068}
4069
vivek mehta4ed66e62016-04-15 23:33:34 -07004070static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071{
vivek mehta4ed66e62016-04-15 23:33:34 -07004072 struct stream_in *in = (struct stream_in *)stream;
4073 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004074}
4075
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004076static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077{
4078 return -ENOSYS;
4079}
4080
4081static int in_standby(struct audio_stream *stream)
4082{
4083 struct stream_in *in = (struct stream_in *)stream;
4084 struct audio_device *adev = in->dev;
4085 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08004086 bool do_stop = true;
4087
Eric Laurent994a6932013-07-17 11:51:42 -07004088 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07004089
4090 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004091
4092 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08004093 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004094 audio_extn_sound_trigger_stop_lab(in);
4095 in->standby = true;
4096 }
4097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004099 if (adev->adm_deregister_stream)
4100 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
4101
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004102 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004104 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08004105 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004106 in->capture_started = false;
4107 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004108 if (in->pcm) {
4109 pcm_close(in->pcm);
4110 in->pcm = NULL;
4111 }
Carter Hsub0c91482019-05-14 18:50:52 +08004112
4113 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
4114 adev->enable_voicerx = false;
4115
Phil Burkbc991042017-02-24 08:06:44 -08004116 if (do_stop) {
4117 status = stop_input_stream(in);
4118 }
Carter Hsub0c91482019-05-14 18:50:52 +08004119
Eric Laurent150dbfe2013-02-27 14:31:02 -08004120 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 }
4122 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004123 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 return status;
4125}
4126
Andy Hungd13f0d32017-06-12 13:58:37 -07004127static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004128{
Andy Hungd13f0d32017-06-12 13:58:37 -07004129 struct stream_in *in = (struct stream_in *)stream;
4130
4131 // We try to get the lock for consistency,
4132 // but it isn't necessary for these variables.
4133 // If we're not in standby, we may be blocked on a read.
4134 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4135 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4136 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4137 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4138
Andy Hung241e36f2019-02-19 12:00:38 -08004139 char buffer[256]; // for statistics formatting
4140 if (in->start_latency_ms.n > 0) {
4141 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4142 dprintf(fd, " Start latency ms: %s\n", buffer);
4143 }
4144
Andy Hungd13f0d32017-06-12 13:58:37 -07004145 if (locked) {
4146 pthread_mutex_unlock(&in->lock);
4147 }
4148
4149 // dump error info
4150 (void)error_log_dump(
4151 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152 return 0;
4153}
4154
4155static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4156{
4157 struct stream_in *in = (struct stream_in *)stream;
4158 struct audio_device *adev = in->dev;
4159 struct str_parms *parms;
4160 char *str;
4161 char value[32];
4162 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004163 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164
Eric Laurent994a6932013-07-17 11:51:42 -07004165 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166 parms = str_parms_create_str(kvpairs);
4167
4168 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4169
Eric Laurenta1478072015-09-21 17:21:52 -07004170 lock_input_stream(in);
4171
Eric Laurent150dbfe2013-02-27 14:31:02 -08004172 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 if (ret >= 0) {
4174 val = atoi(value);
4175 /* no audio source uses val == 0 */
4176 if ((in->source != val) && (val != 0)) {
4177 in->source = val;
4178 }
4179 }
4180
4181 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004183 if (ret >= 0) {
4184 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004185 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004186
4187 // Workaround: If routing to an non existing usb device, fail gracefully
4188 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004189 int card;
4190 if (audio_is_usb_in_device(val) &&
4191 (card = get_alive_usb_card(parms)) >= 0) {
4192
4193 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004194 status = -ENOSYS;
4195 } else {
4196
4197 in->device = val;
4198 /* If recording is in progress, change the tx device to new device */
4199 if (!in->standby) {
4200 ALOGV("update input routing change");
4201 // inform adm before actual routing to prevent glitches.
4202 if (adev->adm_on_routing_change) {
4203 adev->adm_on_routing_change(adev->adm_data,
4204 in->capture_handle);
4205 }
4206 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004207 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 }
4210 }
4211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004213 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
4215 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004216 ALOGV("%s: exit: status(%d)", __func__, status);
4217 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218}
4219
Haynes Mathew George569b7482017-05-08 14:44:27 -07004220static char* in_get_parameters(const struct audio_stream *stream,
4221 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004223 struct stream_in *in = (struct stream_in *)stream;
4224 struct str_parms *query = str_parms_create_str(keys);
4225 char *str;
4226 struct str_parms *reply = str_parms_create();
4227 bool replied = false;
4228
4229 ALOGV("%s: enter: keys - %s", __func__, keys);
4230 replied |= stream_get_parameter_channels(query, reply,
4231 &in->supported_channel_masks[0]);
4232 replied |= stream_get_parameter_formats(query, reply,
4233 &in->supported_formats[0]);
4234 replied |= stream_get_parameter_rates(query, reply,
4235 &in->supported_sample_rates[0]);
4236 if (replied) {
4237 str = str_parms_to_str(reply);
4238 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004239 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004240 }
4241 str_parms_destroy(query);
4242 str_parms_destroy(reply);
4243 ALOGV("%s: exit: returns - %s", __func__, str);
4244 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245}
4246
Eric Laurent51f3c662018-04-10 18:21:34 -07004247static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248{
Eric Laurent51f3c662018-04-10 18:21:34 -07004249 struct stream_in *in = (struct stream_in *)stream;
4250 char mixer_ctl_name[128];
4251 struct mixer_ctl *ctl;
4252 int ctl_value;
4253
4254 ALOGV("%s: gain %f", __func__, gain);
4255
4256 if (stream == NULL)
4257 return -EINVAL;
4258
4259 /* in_set_gain() only used to silence MMAP capture for now */
4260 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4261 return -ENOSYS;
4262
4263 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4264
4265 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4266 if (!ctl) {
4267 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4268 __func__, mixer_ctl_name);
4269 return -ENOSYS;
4270 }
4271
4272 if (gain < RECORD_GAIN_MIN)
4273 gain = RECORD_GAIN_MIN;
4274 else if (gain > RECORD_GAIN_MAX)
4275 gain = RECORD_GAIN_MAX;
4276 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4277
4278 mixer_ctl_set_value(ctl, 0, ctl_value);
4279 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280}
4281
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004282static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4283{
4284 if (!stream || !parms)
4285 return;
4286
4287 struct stream_in *in = (struct stream_in *)stream;
4288 struct audio_device *adev = in->dev;
4289
4290 card_status_t status;
4291 int card;
4292 if (parse_snd_card_status(parms, &card, &status) < 0)
4293 return;
4294
4295 pthread_mutex_lock(&adev->lock);
4296 bool valid_cb = (card == adev->snd_card);
4297 pthread_mutex_unlock(&adev->lock);
4298
4299 if (!valid_cb)
4300 return;
4301
4302 lock_input_stream(in);
4303 if (in->card_status != status)
4304 in->card_status = status;
4305 pthread_mutex_unlock(&in->lock);
4306
4307 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4308 use_case_table[in->usecase],
4309 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4310
4311 // a better solution would be to report error back to AF and let
4312 // it put the stream to standby
4313 if (status == CARD_STATUS_OFFLINE)
4314 in_standby(&in->stream.common);
4315
4316 return;
4317}
4318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4320 size_t bytes)
4321{
4322 struct stream_in *in = (struct stream_in *)stream;
4323 struct audio_device *adev = in->dev;
4324 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004325 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004326 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327
Eric Laurenta1478072015-09-21 17:21:52 -07004328 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004329 const size_t frame_size = audio_stream_in_frame_size(stream);
4330 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004331
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004332 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004333 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004334 /* Read from sound trigger HAL */
4335 audio_extn_sound_trigger_read(in, buffer, bytes);
4336 pthread_mutex_unlock(&in->lock);
4337 return bytes;
4338 }
4339
Eric Laurent0e46adf2016-12-16 12:49:24 -08004340 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4341 ret = -ENOSYS;
4342 goto exit;
4343 }
4344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004345 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004346 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4347
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004348 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004350 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 goto exit;
4353 }
4354 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004355
4356 // log startup time in ms.
4357 simple_stats_log(
4358 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360
Andy Hungd13f0d32017-06-12 13:58:37 -07004361 // errors that occur here are read errors.
4362 error_code = ERROR_CODE_READ;
4363
Haynes Mathew George03c40102016-01-29 17:57:48 -08004364 //what's the duration requested by the client?
4365 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4366 in->config.rate;
4367 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004368
Haynes Mathew George03c40102016-01-29 17:57:48 -08004369 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004371 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004372 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004373 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004374 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004375 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004376 if (ret < 0) {
4377 ALOGE("Failed to read w/err %s", strerror(errno));
4378 ret = -errno;
4379 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004380 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4381 if (bytes % 4 == 0) {
4382 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4383 int_buf_stream = buffer;
4384 for (size_t itt=0; itt < bytes/4 ; itt++) {
4385 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004386 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004387 } else {
4388 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4389 ret = -EINVAL;
4390 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004391 }
4392 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 }
4394
Haynes Mathew George03c40102016-01-29 17:57:48 -08004395 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397 /*
4398 * Instead of writing zeroes here, we could trust the hardware
4399 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004400 * 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 -08004401 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004402 if (ret == 0 && adev->mic_muted &&
4403 !voice_is_in_call_rec_stream(in) &&
4404 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004406 in->frames_muted += frames;
4407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408
4409exit:
4410 pthread_mutex_unlock(&in->lock);
4411
4412 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004413 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 in_standby(&in->stream.common);
4415 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004416 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004417 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004418 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004419 }
4420 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004421 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 }
4423 return bytes;
4424}
4425
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004426static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427{
4428 return 0;
4429}
4430
Andy Hung6ebe5962016-01-15 17:46:57 -08004431static int in_get_capture_position(const struct audio_stream_in *stream,
4432 int64_t *frames, int64_t *time)
4433{
4434 if (stream == NULL || frames == NULL || time == NULL) {
4435 return -EINVAL;
4436 }
4437 struct stream_in *in = (struct stream_in *)stream;
4438 int ret = -ENOSYS;
4439
4440 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004441 // note: ST sessions do not close the alsa pcm driver synchronously
4442 // on standby. Therefore, we may return an error even though the
4443 // pcm stream is still opened.
4444 if (in->standby) {
4445 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4446 "%s stream in standby but pcm not NULL for non ST session", __func__);
4447 goto exit;
4448 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004449 if (in->pcm) {
4450 struct timespec timestamp;
4451 unsigned int avail;
4452 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4453 *frames = in->frames_read + avail;
4454 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4455 ret = 0;
4456 }
4457 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004458exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004459 pthread_mutex_unlock(&in->lock);
4460 return ret;
4461}
4462
Carter Hsub0c91482019-05-14 18:50:52 +08004463static int in_update_effect_list(bool add, effect_handle_t effect,
4464 struct listnode *head)
4465{
4466 struct listnode *node;
4467 struct in_effect_list *elist = NULL;
4468 struct in_effect_list *target = NULL;
4469 int ret = 0;
4470
4471 if (!head)
4472 return ret;
4473
4474 list_for_each(node, head) {
4475 elist = node_to_item(node, struct in_effect_list, list);
4476 if (elist->handle == effect) {
4477 target = elist;
4478 break;
4479 }
4480 }
4481
4482 if (add) {
4483 if (target) {
4484 ALOGD("effect %p already exist", effect);
4485 return ret;
4486 }
4487
4488 target = (struct in_effect_list *)
4489 calloc(1, sizeof(struct in_effect_list));
4490
4491 if (!target) {
4492 ALOGE("%s:fail to allocate memory", __func__);
4493 return -ENOMEM;
4494 }
4495
4496 target->handle = effect;
4497 list_add_tail(head, &target->list);
4498 } else {
4499 if (target) {
4500 list_remove(&target->list);
4501 free(target);
4502 }
4503 }
4504
4505 return ret;
4506}
4507
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004508static int add_remove_audio_effect(const struct audio_stream *stream,
4509 effect_handle_t effect,
4510 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004511{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004512 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004513 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004514 int status = 0;
4515 effect_descriptor_t desc;
4516
4517 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004518 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4519
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004520 if (status != 0)
4521 return status;
4522
Eric Laurenta1478072015-09-21 17:21:52 -07004523 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004524 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004525 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004526 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004527 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004528 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsub0c91482019-05-14 18:50:52 +08004529
4530 in_update_effect_list(enable, effect, &in->aec_list);
4531 enable = !list_empty(&in->aec_list);
4532 if (enable == in->enable_aec)
4533 goto exit;
4534
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004535 in->enable_aec = enable;
Carter Hsub0c91482019-05-14 18:50:52 +08004536 ALOGD("AEC enable %d", enable);
4537
vivek mehta733c1df2016-04-04 15:09:24 -07004538 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4539 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4540 adev->enable_voicerx = enable;
4541 struct audio_usecase *usecase;
4542 struct listnode *node;
4543 list_for_each(node, &adev->usecase_list) {
4544 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004545 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004546 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004547 }
4548 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004549 if (!in->standby
4550 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004551 select_devices(in->dev, in->usecase);
4552 }
Carter Hsub0c91482019-05-14 18:50:52 +08004553 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
4554
4555 in_update_effect_list(enable, effect, &in->ns_list);
4556 enable = !list_empty(&in->ns_list);
4557 if (enable == in->enable_ns)
4558 goto exit;
4559
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004560 in->enable_ns = enable;
Carter Hsub0c91482019-05-14 18:50:52 +08004561 ALOGD("NS enable %d", enable);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004562 if (!in->standby) {
4563 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4564 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4565 select_devices(in->dev, in->usecase);
4566 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004567 }
Carter Hsub0c91482019-05-14 18:50:52 +08004568exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004569 pthread_mutex_unlock(&in->dev->lock);
4570 pthread_mutex_unlock(&in->lock);
4571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 return 0;
4573}
4574
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004575static int in_add_audio_effect(const struct audio_stream *stream,
4576 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577{
Eric Laurent994a6932013-07-17 11:51:42 -07004578 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004579 return add_remove_audio_effect(stream, effect, true);
4580}
4581
4582static int in_remove_audio_effect(const struct audio_stream *stream,
4583 effect_handle_t effect)
4584{
Eric Laurent994a6932013-07-17 11:51:42 -07004585 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004586 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004587}
4588
Eric Laurent0e46adf2016-12-16 12:49:24 -08004589static int in_stop(const struct audio_stream_in* stream)
4590{
4591 struct stream_in *in = (struct stream_in *)stream;
4592 struct audio_device *adev = in->dev;
4593
4594 int ret = -ENOSYS;
4595 ALOGV("%s", __func__);
4596 pthread_mutex_lock(&adev->lock);
4597 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4598 in->capture_started && in->pcm != NULL) {
4599 pcm_stop(in->pcm);
4600 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004601 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004602 }
4603 pthread_mutex_unlock(&adev->lock);
4604 return ret;
4605}
4606
4607static int in_start(const struct audio_stream_in* stream)
4608{
4609 struct stream_in *in = (struct stream_in *)stream;
4610 struct audio_device *adev = in->dev;
4611 int ret = -ENOSYS;
4612
4613 ALOGV("%s in %p", __func__, in);
4614 pthread_mutex_lock(&adev->lock);
4615 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4616 !in->capture_started && in->pcm != NULL) {
4617 if (!in->capture_started) {
4618 ret = start_input_stream(in);
4619 if (ret == 0) {
4620 in->capture_started = true;
4621 }
4622 }
4623 }
4624 pthread_mutex_unlock(&adev->lock);
4625 return ret;
4626}
4627
Phil Burk8a6a1652019-03-25 10:15:59 -07004628// Read offset for the positional timestamp from a persistent vendor property.
4629// This is to workaround apparent inaccuracies in the timing information that
4630// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004631static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004632 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004633 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004634 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004635 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4636 return mmap_time_offset_micros * (int64_t)1000;
4637}
4638
Eric Laurent0e46adf2016-12-16 12:49:24 -08004639static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4640 int32_t min_size_frames,
4641 struct audio_mmap_buffer_info *info)
4642{
4643 struct stream_in *in = (struct stream_in *)stream;
4644 struct audio_device *adev = in->dev;
4645 int ret = 0;
4646 unsigned int offset1;
4647 unsigned int frames1;
4648 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004649 uint32_t mmap_size;
4650 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004651
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004652 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004653 pthread_mutex_lock(&adev->lock);
4654 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004655
Eric Laurent0e46adf2016-12-16 12:49:24 -08004656 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004657 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004658 ret = -EINVAL;
4659 goto exit;
4660 }
4661 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004662 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004663 ALOGV("%s in %p", __func__, in);
4664 ret = -ENOSYS;
4665 goto exit;
4666 }
4667 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4668 if (in->pcm_device_id < 0) {
4669 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4670 __func__, in->pcm_device_id, in->usecase);
4671 ret = -EINVAL;
4672 goto exit;
4673 }
Phil Burkbc991042017-02-24 08:06:44 -08004674
4675 adjust_mmap_period_count(&in->config, min_size_frames);
4676
Eric Laurent0e46adf2016-12-16 12:49:24 -08004677 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4678 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4679 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4680 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4681 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4682 step = "open";
4683 ret = -ENODEV;
4684 goto exit;
4685 }
4686
4687 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4688 if (ret < 0) {
4689 step = "begin";
4690 goto exit;
4691 }
4692 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004693 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004694 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004695 ret = platform_get_mmap_data_fd(adev->platform,
4696 in->pcm_device_id, 1 /*capture*/,
4697 &info->shared_memory_fd,
4698 &mmap_size);
4699 if (ret < 0) {
4700 // Fall back to non exclusive mode
4701 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4702 } else {
4703 if (mmap_size < buffer_size) {
4704 step = "mmap";
4705 goto exit;
4706 }
4707 // FIXME: indicate exclusive mode support by returning a negative buffer size
4708 info->buffer_size_frames *= -1;
4709 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004710
Haynes Mathew George96483a22017-03-28 14:52:47 -07004711 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004712
4713 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4714 if (ret < 0) {
4715 step = "commit";
4716 goto exit;
4717 }
4718
Phil Burkc4714fc2019-02-16 22:28:11 -08004719 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4720
Phil Burkbc991042017-02-24 08:06:44 -08004721 in->standby = false;
4722 ret = 0;
4723
Eric Laurent0e46adf2016-12-16 12:49:24 -08004724 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4725 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004726
4727exit:
4728 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004729 if (in->pcm == NULL) {
4730 ALOGE("%s: %s - %d", __func__, step, ret);
4731 } else {
4732 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004733 pcm_close(in->pcm);
4734 in->pcm = NULL;
4735 }
4736 }
4737 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004738 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004739 return ret;
4740}
4741
4742static int in_get_mmap_position(const struct audio_stream_in *stream,
4743 struct audio_mmap_position *position)
4744{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004745 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004746 struct stream_in *in = (struct stream_in *)stream;
4747 ALOGVV("%s", __func__);
4748 if (position == NULL) {
4749 return -EINVAL;
4750 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004751 lock_input_stream(in);
4752 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4753 in->pcm == NULL) {
4754 ret = -ENOSYS;
4755 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004756 }
4757 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004758 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004759 if (ret < 0) {
4760 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004761 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004762 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004763 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4764 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004765
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004766exit:
4767 pthread_mutex_unlock(&in->lock);
4768 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004769}
4770
jiabin8962a4d2018-03-19 18:21:24 -07004771static int in_get_active_microphones(const struct audio_stream_in *stream,
4772 struct audio_microphone_characteristic_t *mic_array,
4773 size_t *mic_count) {
4774 struct stream_in *in = (struct stream_in *)stream;
4775 struct audio_device *adev = in->dev;
4776 ALOGVV("%s", __func__);
4777
4778 lock_input_stream(in);
4779 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004780 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004781 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004782 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004783 pthread_mutex_unlock(&adev->lock);
4784 pthread_mutex_unlock(&in->lock);
4785
4786 return ret;
4787}
4788
4789static int adev_get_microphones(const struct audio_hw_device *dev,
4790 struct audio_microphone_characteristic_t *mic_array,
4791 size_t *mic_count) {
4792 struct audio_device *adev = (struct audio_device *)dev;
4793 ALOGVV("%s", __func__);
4794
4795 pthread_mutex_lock(&adev->lock);
4796 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4797 pthread_mutex_unlock(&adev->lock);
4798
4799 return ret;
4800}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004801
Paul McLean57530d52018-12-17 08:24:21 -07004802static int in_set_microphone_direction(const struct audio_stream_in *stream,
4803 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004804 struct stream_in *in = (struct stream_in *)stream;
4805
4806 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4807
4808 in->direction = dir;
4809
4810 if (in->standby)
4811 return 0;
4812
4813 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004814}
4815
4816static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004817 struct stream_in *in = (struct stream_in *)stream;
4818
4819 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4820
4821 if (zoom > 1.0 || zoom < -1.0)
4822 return -EINVAL;
4823
4824 in->zoom = zoom;
4825
4826 if (in->standby)
4827 return 0;
4828
4829 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004830}
4831
juyuchenba338cd2019-01-21 11:57:17 +08004832static void in_update_sink_metadata(struct audio_stream_in *stream,
4833 const struct sink_metadata *sink_metadata) {
4834
4835 if (stream == NULL
4836 || sink_metadata == NULL
4837 || sink_metadata->tracks == NULL) {
4838 return;
4839 }
4840
4841 int error = 0;
4842 struct stream_in *in = (struct stream_in *)stream;
4843 struct audio_device *adev = in->dev;
4844 audio_devices_t device = AUDIO_DEVICE_NONE;
4845
4846 if (sink_metadata->track_count != 0)
4847 device = sink_metadata->tracks->dest_device;
4848
4849 lock_input_stream(in);
4850 pthread_mutex_lock(&adev->lock);
4851 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4852
4853 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4854 && device != AUDIO_DEVICE_NONE
4855 && adev->voice_tx_output != NULL) {
4856 /* Use the rx device from afe-proxy record to route voice call because
4857 there is no routing if tx device is on primary hal and rx device
4858 is on other hal during voice call. */
4859 adev->voice_tx_output->devices = device;
4860
4861 if (!voice_is_call_state_active(adev)) {
4862 if (adev->mode == AUDIO_MODE_IN_CALL) {
4863 adev->current_call_output = adev->voice_tx_output;
4864 error = voice_start_call(adev);
4865 if (error != 0)
4866 ALOGE("%s: start voice call failed %d", __func__, error);
4867 }
4868 } else {
4869 adev->current_call_output = adev->voice_tx_output;
4870 voice_update_devices_for_all_voice_usecases(adev);
4871 }
4872 }
4873
4874 pthread_mutex_unlock(&adev->lock);
4875 pthread_mutex_unlock(&in->lock);
4876}
4877
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004878static int adev_open_output_stream(struct audio_hw_device *dev,
4879 audio_io_handle_t handle,
4880 audio_devices_t devices,
4881 audio_output_flags_t flags,
4882 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004883 struct audio_stream_out **stream_out,
4884 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885{
4886 struct audio_device *adev = (struct audio_device *)dev;
4887 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004888 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004889 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4890 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4891 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004892 bool force_haptic_path =
4893 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894
Andy Hungd9653bd2017-08-01 19:31:39 -07004895 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4896 return -ENOSYS;
4897 }
4898
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004899 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4900 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004901
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004902 *stream_out = NULL;
4903 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4904
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004905 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004907 if (devices == AUDIO_DEVICE_NONE)
4908 devices = AUDIO_DEVICE_OUT_SPEAKER;
4909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004910 out->flags = flags;
4911 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004912 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004913 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004914 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004915
4916 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004917 if ((is_hdmi || is_usb_dev) &&
4918 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4919 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4920 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004921 audio_format_t req_format = config->format;
4922 audio_channel_mask_t req_channel_mask = config->channel_mask;
4923 uint32_t req_sample_rate = config->sample_rate;
4924
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004925 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004926 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004927 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004928 if (config->sample_rate == 0)
4929 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004930 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004931 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4932 if (config->format == AUDIO_FORMAT_DEFAULT)
4933 config->format = AUDIO_FORMAT_PCM_16_BIT;
4934 } else if (is_usb_dev) {
4935 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4936 &config->format,
4937 &out->supported_formats[0],
4938 MAX_SUPPORTED_FORMATS,
4939 &config->channel_mask,
4940 &out->supported_channel_masks[0],
4941 MAX_SUPPORTED_CHANNEL_MASKS,
4942 &config->sample_rate,
4943 &out->supported_sample_rates[0],
4944 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004945 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004946 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004947 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004948 if (ret != 0) {
4949 // For MMAP NO IRQ, allow conversions in ADSP
4950 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4951 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004952
Eric Laurentab805ee2018-03-30 12:20:38 -07004953 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4954 config->sample_rate = req_sample_rate;
4955 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4956 config->channel_mask = req_channel_mask;
4957 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4958 config->format = req_format;
4959 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004960
Haynes Mathew George569b7482017-05-08 14:44:27 -07004961 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004962 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004963 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004964 if (is_hdmi) {
4965 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4966 out->config = pcm_config_hdmi_multi;
4967 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4968 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4969 out->config = pcm_config_mmap_playback;
4970 out->stream.start = out_start;
4971 out->stream.stop = out_stop;
4972 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4973 out->stream.get_mmap_position = out_get_mmap_position;
4974 } else {
4975 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4976 out->config = pcm_config_hifi;
4977 }
4978
4979 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004980 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004981 if (is_hdmi) {
4982 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4983 audio_bytes_per_sample(out->format));
4984 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004985 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004986 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004987 pthread_mutex_lock(&adev->lock);
4988 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4989 pthread_mutex_unlock(&adev->lock);
4990
4991 // reject offload during card offline to allow
4992 // fallback to s/w paths
4993 if (offline) {
4994 ret = -ENODEV;
4995 goto error_open;
4996 }
4997
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004998 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4999 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
5000 ALOGE("%s: Unsupported Offload information", __func__);
5001 ret = -EINVAL;
5002 goto error_open;
5003 }
5004 if (!is_supported_format(config->offload_info.format)) {
5005 ALOGE("%s: Unsupported audio format", __func__);
5006 ret = -EINVAL;
5007 goto error_open;
5008 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005009 out->sample_rate = config->offload_info.sample_rate;
5010 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
5011 out->channel_mask = config->offload_info.channel_mask;
5012 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
5013 out->channel_mask = config->channel_mask;
5014 else
5015 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5016
5017 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005018
5019 out->compr_config.codec = (struct snd_codec *)
5020 calloc(1, sizeof(struct snd_codec));
5021
5022 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005023
5024 out->stream.set_callback = out_set_callback;
5025 out->stream.pause = out_pause;
5026 out->stream.resume = out_resume;
5027 out->stream.drain = out_drain;
5028 out->stream.flush = out_flush;
5029
5030 out->compr_config.codec->id =
5031 get_snd_codec_id(config->offload_info.format);
5032 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
5033 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005034 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005035 out->compr_config.codec->bit_rate =
5036 config->offload_info.bit_rate;
5037 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005038 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005039 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
5040
5041 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
5042 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005043
5044 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005045 create_offload_callback_thread(out);
5046 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
5047 __func__, config->offload_info.version,
5048 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02005049 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
5050 switch (config->sample_rate) {
5051 case 0:
5052 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5053 break;
5054 case 8000:
5055 case 16000:
5056 case 48000:
5057 out->sample_rate = config->sample_rate;
5058 break;
5059 default:
5060 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
5061 config->sample_rate);
5062 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5063 ret = -EINVAL;
5064 goto error_open;
5065 }
5066 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
5067 switch (config->channel_mask) {
5068 case AUDIO_CHANNEL_NONE:
5069 case AUDIO_CHANNEL_OUT_STEREO:
5070 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5071 break;
5072 default:
5073 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
5074 config->channel_mask);
5075 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5076 ret = -EINVAL;
5077 goto error_open;
5078 }
5079 switch (config->format) {
5080 case AUDIO_FORMAT_DEFAULT:
5081 case AUDIO_FORMAT_PCM_16_BIT:
5082 out->format = AUDIO_FORMAT_PCM_16_BIT;
5083 break;
5084 default:
5085 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
5086 config->format);
5087 config->format = AUDIO_FORMAT_PCM_16_BIT;
5088 ret = -EINVAL;
5089 goto error_open;
5090 }
5091
5092 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005093 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005094 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005095 case 0:
5096 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
5097 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07005098 case 8000:
5099 case 16000:
5100 case 48000:
5101 out->sample_rate = config->sample_rate;
5102 break;
5103 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005104 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
5105 config->sample_rate);
5106 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5107 ret = -EINVAL;
5108 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005109 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005110 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
5111 switch (config->channel_mask) {
5112 case AUDIO_CHANNEL_NONE:
5113 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5114 break;
5115 case AUDIO_CHANNEL_OUT_STEREO:
5116 out->channel_mask = config->channel_mask;
5117 break;
5118 default:
5119 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
5120 config->channel_mask);
5121 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5122 ret = -EINVAL;
5123 break;
5124 }
5125 switch (config->format) {
5126 case AUDIO_FORMAT_DEFAULT:
5127 out->format = AUDIO_FORMAT_PCM_16_BIT;
5128 break;
5129 case AUDIO_FORMAT_PCM_16_BIT:
5130 out->format = config->format;
5131 break;
5132 default:
5133 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
5134 config->format);
5135 config->format = AUDIO_FORMAT_PCM_16_BIT;
5136 ret = -EINVAL;
5137 break;
5138 }
5139 if (ret != 0)
5140 goto error_open;
5141
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005142 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
5143 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005144 out->config.rate = out->sample_rate;
5145 out->config.channels =
5146 audio_channel_count_from_out_mask(out->channel_mask);
5147 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005148 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005149 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
5150 switch (config->sample_rate) {
5151 case 0:
5152 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5153 break;
5154 case 8000:
5155 case 16000:
5156 case 32000:
5157 case 48000:
5158 out->sample_rate = config->sample_rate;
5159 break;
5160 default:
5161 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
5162 config->sample_rate);
5163 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
5164 ret = -EINVAL;
5165 break;
5166 }
Eric Laurentad2dde92017-09-20 18:27:31 -07005167 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005168 switch (config->channel_mask) {
5169 case AUDIO_CHANNEL_NONE:
5170 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5171 break;
5172 case AUDIO_CHANNEL_OUT_STEREO:
5173 out->channel_mask = config->channel_mask;
5174 break;
5175 default:
5176 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
5177 config->channel_mask);
5178 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5179 ret = -EINVAL;
5180 break;
5181 }
5182 switch (config->format) {
5183 case AUDIO_FORMAT_DEFAULT:
5184 out->format = AUDIO_FORMAT_PCM_16_BIT;
5185 break;
5186 case AUDIO_FORMAT_PCM_16_BIT:
5187 out->format = config->format;
5188 break;
5189 default:
5190 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5191 config->format);
5192 config->format = AUDIO_FORMAT_PCM_16_BIT;
5193 ret = -EINVAL;
5194 break;
5195 }
5196 if (ret != 0)
5197 goto error_open;
5198
vivek mehtaa68fea62017-06-08 19:04:02 -07005199 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005200 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5201 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005202 out->config.rate = out->sample_rate;
5203 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005204 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005205 out->sample_rate,
5206 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005207 out->config.channels,
5208 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005209 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005210 out->config.period_size = buffer_size / frame_size;
5211 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5212 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005214 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005215 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5216 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005217 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005218 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5219 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005220 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005221 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005222 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005223 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005224 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005225 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5226 out->config = pcm_config_mmap_playback;
5227 out->stream.start = out_start;
5228 out->stream.stop = out_stop;
5229 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5230 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005231 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005232 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5233 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5234 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5235 if (adev->haptic_pcm_device_id < 0) {
5236 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5237 __func__, adev->haptic_pcm_device_id, out->usecase);
5238 ret = -ENOSYS;
5239 goto error_open;
5240 }
5241 out->config = pcm_config_haptics_audio;
5242 if (force_haptic_path)
5243 adev->haptics_config = pcm_config_haptics_audio;
5244 else
5245 adev->haptics_config = pcm_config_haptics;
5246 } else {
5247 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5248 out->config = pcm_config_low_latency;
5249 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005250 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005251
5252 if (config->sample_rate == 0) {
5253 out->sample_rate = out->config.rate;
5254 } else {
5255 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005256 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005257
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005258 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5259 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5260 } else {
5261 out->channel_mask = config->channel_mask;
5262 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005263
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005264 if (config->format == AUDIO_FORMAT_DEFAULT)
5265 out->format = audio_format_from_pcm_format(out->config.format);
5266 else if (!audio_is_linear_pcm(config->format)) {
5267 config->format = AUDIO_FORMAT_PCM_16_BIT;
5268 ret = -EINVAL;
5269 goto error_open;
5270 } else {
5271 out->format = config->format;
5272 }
5273
5274 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005275
5276 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5277 out->config.channels =
5278 audio_channel_count_from_out_mask(out->channel_mask &
5279 ~AUDIO_CHANNEL_HAPTIC_ALL);
5280
5281 if (force_haptic_path) {
5282 out->config.channels = 1;
5283 adev->haptics_config.channels = 1;
5284 } else {
5285 adev->haptics_config.channels =
5286 audio_channel_count_from_out_mask(out->channel_mask &
5287 AUDIO_CHANNEL_HAPTIC_ALL);
5288 }
5289 } else {
5290 out->config.channels =
5291 audio_channel_count_from_out_mask(out->channel_mask);
5292 }
5293
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005294 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5295 out->config.format = pcm_format_from_audio_format(out->format);
5296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005297 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005298
5299 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5300 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005301 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005302 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5303 __func__, config->sample_rate, config->format, config->channel_mask);
5304 config->sample_rate = out->sample_rate;
5305 config->format = out->format;
5306 config->channel_mask = out->channel_mask;
5307 ret = -EINVAL;
5308 goto error_open;
5309 }
5310
Andy Hung6fcba9c2014-03-18 11:53:32 -07005311 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5312 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005313
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005314 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005315 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005316 adev->primary_output = out;
5317 else {
5318 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005319 ret = -EEXIST;
5320 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005321 }
5322 }
5323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 /* Check if this usecase is already existing */
5325 pthread_mutex_lock(&adev->lock);
5326 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5327 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005328 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005329 ret = -EEXIST;
5330 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 }
5332 pthread_mutex_unlock(&adev->lock);
5333
5334 out->stream.common.get_sample_rate = out_get_sample_rate;
5335 out->stream.common.set_sample_rate = out_set_sample_rate;
5336 out->stream.common.get_buffer_size = out_get_buffer_size;
5337 out->stream.common.get_channels = out_get_channels;
5338 out->stream.common.get_format = out_get_format;
5339 out->stream.common.set_format = out_set_format;
5340 out->stream.common.standby = out_standby;
5341 out->stream.common.dump = out_dump;
5342 out->stream.common.set_parameters = out_set_parameters;
5343 out->stream.common.get_parameters = out_get_parameters;
5344 out->stream.common.add_audio_effect = out_add_audio_effect;
5345 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5346 out->stream.get_latency = out_get_latency;
5347 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005348#ifdef NO_AUDIO_OUT
5349 out->stream.write = out_write_for_no_output;
5350#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005351 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005352#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005353 out->stream.get_render_position = out_get_render_position;
5354 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005355 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356
Eric Laurent0e46adf2016-12-16 12:49:24 -08005357 if (out->realtime)
5358 out->af_period_multiplier = af_period_multiplier;
5359 else
5360 out->af_period_multiplier = 1;
5361
Andy Hung572633e2019-02-19 11:58:24 -08005362 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5363
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005364 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005365 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005366 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005368 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005369 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005370 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372 config->format = out->stream.common.get_format(&out->stream.common);
5373 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5374 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5375
Kevin Rocarda325aa22018-04-03 09:15:52 -07005376 register_format(out->format, out->supported_formats);
5377 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5378 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5379
Andy Hunga452b0a2017-03-15 14:51:15 -07005380 out->error_log = error_log_create(
5381 ERROR_LOG_ENTRIES,
5382 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5383
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005384 /*
5385 By locking output stream before registering, we allow the callback
5386 to update stream's state only after stream's initial state is set to
5387 adev state.
5388 */
5389 lock_output_stream(out);
5390 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5391 pthread_mutex_lock(&adev->lock);
5392 out->card_status = adev->card_status;
5393 pthread_mutex_unlock(&adev->lock);
5394 pthread_mutex_unlock(&out->lock);
5395
vivek mehta4a824772017-06-08 19:05:49 -07005396 stream_app_type_cfg_init(&out->app_type_cfg);
5397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005398 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005399
Eric Laurent994a6932013-07-17 11:51:42 -07005400 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005401 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005402
5403error_open:
5404 free(out);
5405 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005406 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005407 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005408}
5409
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005410static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005411 struct audio_stream_out *stream)
5412{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005413 struct stream_out *out = (struct stream_out *)stream;
5414 struct audio_device *adev = out->dev;
5415
Eric Laurent994a6932013-07-17 11:51:42 -07005416 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005417
5418 // must deregister from sndmonitor first to prevent races
5419 // between the callback and close_stream
5420 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005421 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005422 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5423 destroy_offload_callback_thread(out);
5424
5425 if (out->compr_config.codec != NULL)
5426 free(out->compr_config.codec);
5427 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005428
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005429 out->a2dp_compress_mute = false;
5430
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005431 if (adev->voice_tx_output == out)
5432 adev->voice_tx_output = NULL;
5433
Andy Hunga452b0a2017-03-15 14:51:15 -07005434 error_log_destroy(out->error_log);
5435 out->error_log = NULL;
5436
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005437 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005438 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005439 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005440 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005441 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442}
5443
5444static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5445{
5446 struct audio_device *adev = (struct audio_device *)dev;
5447 struct str_parms *parms;
5448 char *str;
5449 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005450 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005452 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005453 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454
Joe Onorato188b6222016-03-01 11:02:27 -08005455 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005456
5457 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458
5459 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005460 status = voice_set_parameters(adev, parms);
5461 if (status != 0) {
5462 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463 }
5464
5465 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5466 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005467 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5469 adev->bluetooth_nrec = true;
5470 else
5471 adev->bluetooth_nrec = false;
5472 }
5473
5474 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5475 if (ret >= 0) {
5476 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5477 adev->screen_off = false;
5478 else
5479 adev->screen_off = true;
5480 }
5481
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005482 ret = str_parms_get_int(parms, "rotation", &val);
5483 if (ret >= 0) {
5484 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005485 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005486 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005487 // FIXME: note that the code below assumes that the speakers are in the correct placement
5488 // relative to the user when the device is rotated 90deg from its default rotation. This
5489 // assumption is device-specific, not platform-specific like this code.
5490 case 270:
5491 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005492 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005493 break;
5494 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005495 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005496 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5497 break;
5498 case 90:
5499 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005500 break;
5501 default:
5502 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005503 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005504 }
Eric Laurent03f09432014-03-25 18:09:11 -07005505 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005506 // check and set swap
5507 // - check if orientation changed and speaker active
5508 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005509 adev->camera_orientation =
5510 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5511#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005512 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005513#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005514 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005515 }
5516
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005517 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5518 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005519 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005520 }
5521
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07005522 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5523 if (ret >= 0) {
5524 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5525 adev->bt_sco_on = true;
5526 else
5527 adev->bt_sco_on = false;
5528 }
5529
David Linee3fe402017-03-13 10:00:42 -07005530 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5531 if (ret >= 0) {
5532 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005533 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005534 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5535 if (ret >= 0) {
5536 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005537 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005538 }
Eric Laurent99dab492017-06-17 15:19:08 -07005539 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005540 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5541 if (ret >= 0) {
5542 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005543 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005544 }
5545 }
5546 }
5547
5548 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, 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_remove_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_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005562 }
5563 }
5564 }
5565
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005566 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005567 audio_extn_ma_set_parameters(adev, parms);
5568
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005569 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5570 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005571 struct audio_usecase *usecase;
5572 struct listnode *node;
5573 list_for_each(node, &adev->usecase_list) {
5574 usecase = node_to_item(node, struct audio_usecase, list);
5575 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005576 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005577 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5578
5579 pthread_mutex_unlock(&adev->lock);
5580 lock_output_stream(usecase->stream.out);
5581 pthread_mutex_lock(&adev->lock);
5582 audio_extn_a2dp_set_handoff_mode(true);
5583 // force device switch to reconfigure encoder
5584 select_devices(adev, usecase->id);
5585 audio_extn_a2dp_set_handoff_mode(false);
5586 pthread_mutex_unlock(&usecase->stream.out->lock);
5587 break;
5588 }
5589 }
5590 }
5591
Eric Laurent5f4ca952018-10-19 17:33:43 -07005592 //FIXME: to be replaced by proper video capture properties API
5593 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5594 if (ret >= 0) {
5595 int camera_facing = CAMERA_FACING_BACK;
5596 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5597 camera_facing = CAMERA_FACING_FRONT;
5598 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5599 camera_facing = CAMERA_FACING_BACK;
5600 else {
5601 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5602 goto done;
5603 }
5604 adev->camera_orientation =
5605 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5606 struct audio_usecase *usecase;
5607 struct listnode *node;
5608 list_for_each(node, &adev->usecase_list) {
5609 usecase = node_to_item(node, struct audio_usecase, list);
5610 struct stream_in *in = usecase->stream.in;
5611 if (usecase->type == PCM_CAPTURE && in != NULL &&
5612 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5613 select_devices(adev, in->usecase);
5614 }
5615 }
5616 }
5617
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005618done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005620 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005621 ALOGV("%s: exit with code(%d)", __func__, status);
5622 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005623}
5624
5625static char* adev_get_parameters(const struct audio_hw_device *dev,
5626 const char *keys)
5627{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005628 struct audio_device *adev = (struct audio_device *)dev;
5629 struct str_parms *reply = str_parms_create();
5630 struct str_parms *query = str_parms_create_str(keys);
5631 char *str;
5632
5633 pthread_mutex_lock(&adev->lock);
5634
5635 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005636 audio_extn_a2dp_get_parameters(query, reply);
5637
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005638 str = str_parms_to_str(reply);
5639 str_parms_destroy(query);
5640 str_parms_destroy(reply);
5641
5642 pthread_mutex_unlock(&adev->lock);
5643 ALOGV("%s: exit: returns - %s", __func__, str);
5644 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005645}
5646
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005647static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005648{
5649 return 0;
5650}
5651
Haynes Mathew George5191a852013-09-11 14:19:36 -07005652static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5653{
5654 int ret;
5655 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005656
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005657 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5658
Haynes Mathew George5191a852013-09-11 14:19:36 -07005659 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005660 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005661 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005662
Haynes Mathew George5191a852013-09-11 14:19:36 -07005663 return ret;
5664}
5665
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005666static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667{
5668 return -ENOSYS;
5669}
5670
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005671static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5672 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005673{
5674 return -ENOSYS;
5675}
5676
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005677static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005678{
5679 return -ENOSYS;
5680}
5681
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005682static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005683{
5684 return -ENOSYS;
5685}
5686
5687static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5688{
5689 struct audio_device *adev = (struct audio_device *)dev;
5690
5691 pthread_mutex_lock(&adev->lock);
5692 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005693 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005695 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5696 voice_is_in_call(adev)) {
5697 voice_stop_call(adev);
5698 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005699
5700 /*
5701 * After stopping the call, it must check if any active capture
5702 * activity device needs to be re-selected.
5703 */
5704 struct audio_usecase *usecase;
5705 struct listnode *node;
5706 list_for_each(node, &adev->usecase_list) {
5707 usecase = node_to_item(node, struct audio_usecase, list);
5708 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5709 select_devices_with_force_switch(adev, usecase->id, true);
5710 }
5711 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005713 }
5714 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005715
5716 audio_extn_extspk_set_mode(adev->extspk, mode);
5717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005718 return 0;
5719}
5720
5721static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5722{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005723 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005724 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725
Eric Laurent2bafff12016-03-17 12:17:23 -07005726 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005727 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005728 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5729 ret = audio_extn_hfp_set_mic_mute(adev, state);
5730 } else {
5731 ret = voice_set_mic_mute(adev, state);
5732 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005733 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005734 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005735
5736 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005737}
5738
5739static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5740{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005741 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005742 return 0;
5743}
5744
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005745static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746 const struct audio_config *config)
5747{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005748 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005749
Eric Laurent74b55762017-07-09 17:04:53 -07005750 /* Don't know if USB HIFI in this context so use true to be conservative */
5751 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5752 true /*is_usb_hifi */) != 0)
5753 return 0;
5754
vivek mehtaa68fea62017-06-08 19:04:02 -07005755 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5756 config->sample_rate, config->format,
5757 channel_count,
5758 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005759}
5760
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005761static bool adev_input_allow_hifi_record(struct audio_device *adev,
5762 audio_devices_t devices,
5763 audio_input_flags_t flags,
5764 audio_source_t source) {
5765 const bool allowed = true;
5766
5767 if (!audio_is_usb_in_device(devices))
5768 return !allowed;
5769
5770 switch (flags) {
5771 case AUDIO_INPUT_FLAG_NONE:
5772 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5773 break;
5774 default:
5775 return !allowed;
5776 }
5777
5778 switch (source) {
5779 case AUDIO_SOURCE_DEFAULT:
5780 case AUDIO_SOURCE_MIC:
5781 case AUDIO_SOURCE_UNPROCESSED:
5782 break;
5783 default:
5784 return !allowed;
5785 }
5786
5787 switch (adev->mode) {
5788 case 0:
5789 break;
5790 default:
5791 return !allowed;
5792 }
5793
5794 return allowed;
5795}
5796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005797static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005798 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005799 audio_devices_t devices,
5800 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005801 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005802 audio_input_flags_t flags,
5803 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005804 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005805{
5806 struct audio_device *adev = (struct audio_device *)dev;
5807 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005808 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005809 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005810 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005811 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005812 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5813 devices,
5814 flags,
5815 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005816 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5817 " sample_rate %u, channel_mask %#x, format %#x",
5818 __func__, flags, is_usb_dev, may_use_hifi_record,
5819 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005821
Andy Hungd9653bd2017-08-01 19:31:39 -07005822 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5823 return -ENOSYS;
5824 }
5825
Eric Laurent74b55762017-07-09 17:04:53 -07005826 if (!(is_usb_dev && may_use_hifi_record)) {
5827 if (config->sample_rate == 0)
5828 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5829 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5830 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5831 if (config->format == AUDIO_FORMAT_DEFAULT)
5832 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005833
Eric Laurent74b55762017-07-09 17:04:53 -07005834 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5835
5836 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5837 return -EINVAL;
5838 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005839
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005840 if (audio_extn_tfa_98xx_is_supported() &&
5841 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005842 return -EINVAL;
5843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005844 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5845
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005846 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005847 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005848
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005849 in->stream.common.get_sample_rate = in_get_sample_rate;
5850 in->stream.common.set_sample_rate = in_set_sample_rate;
5851 in->stream.common.get_buffer_size = in_get_buffer_size;
5852 in->stream.common.get_channels = in_get_channels;
5853 in->stream.common.get_format = in_get_format;
5854 in->stream.common.set_format = in_set_format;
5855 in->stream.common.standby = in_standby;
5856 in->stream.common.dump = in_dump;
5857 in->stream.common.set_parameters = in_set_parameters;
5858 in->stream.common.get_parameters = in_get_parameters;
5859 in->stream.common.add_audio_effect = in_add_audio_effect;
5860 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5861 in->stream.set_gain = in_set_gain;
5862 in->stream.read = in_read;
5863 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005864 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005865 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005866 in->stream.set_microphone_direction = in_set_microphone_direction;
5867 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005868 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005869
5870 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005871 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005872 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005873 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005874 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005875 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005876 in->direction = MIC_DIRECTION_UNSPECIFIED;
5877 in->zoom = 0;
Carter Hsub0c91482019-05-14 18:50:52 +08005878 list_init(&in->aec_list);
5879 list_init(&in->ns_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005880
Andy Hung88ce1d92018-10-29 18:31:12 -07005881 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005882 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5883 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5884 /* Force channel config requested to mono if incall
5885 record is being requested for only uplink/downlink */
5886 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5887 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5888 ret = -EINVAL;
5889 goto err_open;
5890 }
5891 }
5892
Haynes Mathew George569b7482017-05-08 14:44:27 -07005893 if (is_usb_dev && may_use_hifi_record) {
5894 /* HiFi record selects an appropriate format, channel, rate combo
5895 depending on sink capabilities*/
5896 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5897 &config->format,
5898 &in->supported_formats[0],
5899 MAX_SUPPORTED_FORMATS,
5900 &config->channel_mask,
5901 &in->supported_channel_masks[0],
5902 MAX_SUPPORTED_CHANNEL_MASKS,
5903 &config->sample_rate,
5904 &in->supported_sample_rates[0],
5905 MAX_SUPPORTED_SAMPLE_RATES);
5906 if (ret != 0) {
5907 ret = -EINVAL;
5908 goto err_open;
5909 }
Eric Laurent74b55762017-07-09 17:04:53 -07005910 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005911 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005912 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005913 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5914 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5915 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5916 bool ret_error = false;
5917 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5918 from HAL is 8_24
5919 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5920 8_24 return error indicating supported format is 8_24
5921 *> In case of any other source requesting 24 bit or float return error
5922 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005923
vivek mehta57ff9b52016-04-28 14:13:08 -07005924 on error flinger will retry with supported format passed
5925 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005926 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005927 config->format = AUDIO_FORMAT_PCM_16_BIT;
5928 ret_error = true;
5929 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5930 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5931 ret_error = true;
5932 }
5933
5934 if (ret_error) {
5935 ret = -EINVAL;
5936 goto err_open;
5937 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005938 }
5939
vivek mehta57ff9b52016-04-28 14:13:08 -07005940 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005941 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005943 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005944 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5945 if (config->sample_rate == 0)
5946 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5947 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5948 config->sample_rate != 8000) {
5949 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5950 ret = -EINVAL;
5951 goto err_open;
5952 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005953
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005954 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5955 config->format = AUDIO_FORMAT_PCM_16_BIT;
5956 ret = -EINVAL;
5957 goto err_open;
5958 }
5959
5960 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5961 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005962 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005963 } else if (is_usb_dev && may_use_hifi_record) {
5964 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5965 in->config = pcm_config_audio_capture;
5966 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005967 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5968 config->sample_rate,
5969 config->format,
5970 channel_count,
5971 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005972 in->config.period_size = buffer_size / frame_size;
5973 in->config.rate = config->sample_rate;
5974 in->af_period_multiplier = 1;
5975 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005976 } else {
5977 in->usecase = USECASE_AUDIO_RECORD;
5978 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005979 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005980 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005981#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005982 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005983#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005984 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005985 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005986 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005987 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005988 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5989 config->sample_rate,
5990 config->format,
5991 channel_count,
5992 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005993 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005994 in->config.rate = config->sample_rate;
5995 in->af_period_multiplier = 1;
5996 } else {
5997 // period size is left untouched for rt mode playback
5998 in->config = pcm_config_audio_capture_rt;
5999 in->af_period_multiplier = af_period_multiplier;
6000 }
6001 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
6002 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07006003 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08006004 in->usecase = USECASE_AUDIO_RECORD_MMAP;
6005 in->config = pcm_config_mmap_capture;
6006 in->stream.start = in_start;
6007 in->stream.stop = in_stop;
6008 in->stream.create_mmap_buffer = in_create_mmap_buffer;
6009 in->stream.get_mmap_position = in_get_mmap_position;
6010 in->af_period_multiplier = 1;
6011 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07006012 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07006013 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07006014 (config->sample_rate == 8000 ||
6015 config->sample_rate == 16000 ||
6016 config->sample_rate == 32000 ||
6017 config->sample_rate == 48000) &&
6018 channel_count == 1) {
6019 in->usecase = USECASE_AUDIO_RECORD_VOIP;
6020 in->config = pcm_config_audio_capture;
6021 frame_size = audio_stream_in_frame_size(&in->stream);
6022 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
6023 config->sample_rate,
6024 config->format,
6025 channel_count, false /*is_low_latency*/);
6026 in->config.period_size = buffer_size / frame_size;
6027 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
6028 in->config.rate = config->sample_rate;
6029 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006030 } else {
6031 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006032 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07006033 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
6034 config->sample_rate,
6035 config->format,
6036 channel_count,
6037 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08006038 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006039 in->config.rate = config->sample_rate;
6040 in->af_period_multiplier = 1;
6041 }
6042 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
6043 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07006044 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08006045
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006046 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07006047 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006048
Kevin Rocarda325aa22018-04-03 09:15:52 -07006049
6050 register_format(in->format, in->supported_formats);
6051 register_channel_mask(in->channel_mask, in->supported_channel_masks);
6052 register_sample_rate(in->sample_rate, in->supported_sample_rates);
6053
Andy Hungd13f0d32017-06-12 13:58:37 -07006054 in->error_log = error_log_create(
6055 ERROR_LOG_ENTRIES,
6056 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
6057
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07006058 /* This stream could be for sound trigger lab,
6059 get sound trigger pcm if present */
6060 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006061
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006062 lock_input_stream(in);
6063 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
6064 pthread_mutex_lock(&adev->lock);
6065 in->card_status = adev->card_status;
6066 pthread_mutex_unlock(&adev->lock);
6067 pthread_mutex_unlock(&in->lock);
6068
vivek mehta4a824772017-06-08 19:05:49 -07006069 stream_app_type_cfg_init(&in->app_type_cfg);
6070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006071 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006072 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006073 return 0;
6074
6075err_open:
6076 free(in);
6077 *stream_in = NULL;
6078 return ret;
6079}
6080
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07006081static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006082 struct audio_stream_in *stream)
6083{
Andy Hungd13f0d32017-06-12 13:58:37 -07006084 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07006085 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08006086
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006087 // must deregister from sndmonitor first to prevent races
6088 // between the callback and close_stream
6089 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006090 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07006091
6092 error_log_destroy(in->error_log);
6093 in->error_log = NULL;
6094
Andy Hung0dbb52b2017-08-09 13:51:38 -07006095 pthread_mutex_destroy(&in->pre_lock);
6096 pthread_mutex_destroy(&in->lock);
6097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006098 free(stream);
6099
6100 return;
6101}
6102
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07006103static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006104{
6105 return 0;
6106}
6107
Andy Hung31aca912014-03-20 17:14:59 -07006108/* verifies input and output devices and their capabilities.
6109 *
6110 * This verification is required when enabling extended bit-depth or
6111 * sampling rates, as not all qcom products support it.
6112 *
6113 * Suitable for calling only on initialization such as adev_open().
6114 * It fills the audio_device use_case_table[] array.
6115 *
6116 * Has a side-effect that it needs to configure audio routing / devices
6117 * in order to power up the devices and read the device parameters.
6118 * It does not acquire any hw device lock. Should restore the devices
6119 * back to "normal state" upon completion.
6120 */
6121static int adev_verify_devices(struct audio_device *adev)
6122{
6123 /* enumeration is a bit difficult because one really wants to pull
6124 * the use_case, device id, etc from the hidden pcm_device_table[].
6125 * In this case there are the following use cases and device ids.
6126 *
6127 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
6128 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006129 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07006130 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
6131 * [USECASE_AUDIO_RECORD] = {0, 0},
6132 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
6133 * [USECASE_VOICE_CALL] = {2, 2},
6134 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006135 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07006136 * USECASE_VOICE_CALL omitted, but possible for either input or output.
6137 */
6138
6139 /* should be the usecases enabled in adev_open_input_stream() */
6140 static const int test_in_usecases[] = {
6141 USECASE_AUDIO_RECORD,
6142 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
6143 };
6144 /* should be the usecases enabled in adev_open_output_stream()*/
6145 static const int test_out_usecases[] = {
6146 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
6147 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
6148 };
6149 static const usecase_type_t usecase_type_by_dir[] = {
6150 PCM_PLAYBACK,
6151 PCM_CAPTURE,
6152 };
6153 static const unsigned flags_by_dir[] = {
6154 PCM_OUT,
6155 PCM_IN,
6156 };
6157
6158 size_t i;
6159 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006160 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07006161 char info[512]; /* for possible debug info */
6162
6163 for (dir = 0; dir < 2; ++dir) {
6164 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
6165 const unsigned flags_dir = flags_by_dir[dir];
6166 const size_t testsize =
6167 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
6168 const int *testcases =
6169 dir ? test_in_usecases : test_out_usecases;
6170 const audio_devices_t audio_device =
6171 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
6172
6173 for (i = 0; i < testsize; ++i) {
6174 const audio_usecase_t audio_usecase = testcases[i];
6175 int device_id;
6176 snd_device_t snd_device;
6177 struct pcm_params **pparams;
6178 struct stream_out out;
6179 struct stream_in in;
6180 struct audio_usecase uc_info;
6181 int retval;
6182
6183 pparams = &adev->use_case_table[audio_usecase];
6184 pcm_params_free(*pparams); /* can accept null input */
6185 *pparams = NULL;
6186
6187 /* find the device ID for the use case (signed, for error) */
6188 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
6189 if (device_id < 0)
6190 continue;
6191
6192 /* prepare structures for device probing */
6193 memset(&uc_info, 0, sizeof(uc_info));
6194 uc_info.id = audio_usecase;
6195 uc_info.type = usecase_type;
6196 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07006197 memset(&in, 0, sizeof(in));
6198 in.device = audio_device;
6199 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
6200 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07006201 }
6202 memset(&out, 0, sizeof(out));
6203 out.devices = audio_device; /* only field needed in select_devices */
6204 uc_info.stream.out = &out;
6205 uc_info.devices = audio_device;
6206 uc_info.in_snd_device = SND_DEVICE_NONE;
6207 uc_info.out_snd_device = SND_DEVICE_NONE;
6208 list_add_tail(&adev->usecase_list, &uc_info.list);
6209
6210 /* select device - similar to start_(in/out)put_stream() */
6211 retval = select_devices(adev, audio_usecase);
6212 if (retval >= 0) {
6213 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6214#if LOG_NDEBUG == 0
6215 if (*pparams) {
6216 ALOGV("%s: (%s) card %d device %d", __func__,
6217 dir ? "input" : "output", card_id, device_id);
6218 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006219 } else {
6220 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6221 }
6222#endif
6223 }
6224
6225 /* deselect device - similar to stop_(in/out)put_stream() */
6226 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006227 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006228 /* 2. Disable the rx device */
6229 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006230 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006231 list_remove(&uc_info.list);
6232 }
6233 }
Andy Hung31aca912014-03-20 17:14:59 -07006234 return 0;
6235}
6236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006237static int adev_close(hw_device_t *device)
6238{
Andy Hung31aca912014-03-20 17:14:59 -07006239 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006240 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006241
6242 if (!adev)
6243 return 0;
6244
6245 pthread_mutex_lock(&adev_init_lock);
6246
6247 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006248 audio_extn_snd_mon_unregister_listener(adev);
6249 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006250 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006251 audio_route_free(adev->audio_route);
6252 free(adev->snd_dev_ref_cnt);
6253 platform_deinit(adev->platform);
6254 audio_extn_extspk_deinit(adev->extspk);
6255 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006256 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006257 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6258 pcm_params_free(adev->use_case_table[i]);
6259 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006260 if (adev->adm_deinit)
6261 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006262 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006263 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006264 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006265
6266 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006267
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 return 0;
6269}
6270
Glenn Kasten4f993392014-05-14 07:30:48 -07006271/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6272 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6273 * just that it _might_ work.
6274 */
6275static int period_size_is_plausible_for_low_latency(int period_size)
6276{
6277 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006278 case 48:
6279 case 96:
6280 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006281 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006282 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006283 case 240:
6284 case 320:
6285 case 480:
6286 return 1;
6287 default:
6288 return 0;
6289 }
6290}
6291
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006292static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6293{
6294 int card;
6295 card_status_t status;
6296
6297 if (!parms)
6298 return;
6299
6300 if (parse_snd_card_status(parms, &card, &status) < 0)
6301 return;
6302
6303 pthread_mutex_lock(&adev->lock);
6304 bool valid_cb = (card == adev->snd_card);
6305 if (valid_cb) {
6306 if (adev->card_status != status) {
6307 adev->card_status = status;
6308 platform_snd_card_update(adev->platform, status);
6309 }
6310 }
6311 pthread_mutex_unlock(&adev->lock);
6312 return;
6313}
6314
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006315/* out and adev lock held */
6316static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6317{
6318 struct audio_usecase *uc_info;
6319 float left_p;
6320 float right_p;
6321 audio_devices_t devices;
6322
6323 uc_info = get_usecase_from_list(adev, out->usecase);
6324 if (uc_info == NULL) {
6325 ALOGE("%s: Could not find the usecase (%d) in the list",
6326 __func__, out->usecase);
6327 return -EINVAL;
6328 }
6329
6330 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6331 out->usecase, use_case_table[out->usecase]);
6332
6333 if (restore) {
6334 // restore A2DP device for active usecases and unmute if required
6335 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6336 !is_a2dp_device(uc_info->out_snd_device)) {
6337 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6338 select_devices(adev, uc_info->id);
6339 pthread_mutex_lock(&out->compr_mute_lock);
6340 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6341 (out->a2dp_compress_mute)) {
6342 out->a2dp_compress_mute = false;
6343 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6344 }
6345 pthread_mutex_unlock(&out->compr_mute_lock);
6346 }
6347 } else {
6348 // mute compress stream if suspended
6349 pthread_mutex_lock(&out->compr_mute_lock);
6350 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6351 (!out->a2dp_compress_mute)) {
6352 if (!out->standby) {
6353 ALOGD("%s: selecting speaker and muting stream", __func__);
6354 devices = out->devices;
6355 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6356 left_p = out->volume_l;
6357 right_p = out->volume_r;
6358 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6359 compress_pause(out->compr);
6360 set_compr_volume(&out->stream, 0.0f, 0.0f);
6361 out->a2dp_compress_mute = true;
6362 select_devices(adev, out->usecase);
6363 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6364 compress_resume(out->compr);
6365 out->devices = devices;
6366 out->volume_l = left_p;
6367 out->volume_r = right_p;
6368 }
6369 }
6370 pthread_mutex_unlock(&out->compr_mute_lock);
6371 }
6372 ALOGV("%s: exit", __func__);
6373 return 0;
6374}
6375
6376int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6377{
6378 int ret = 0;
6379
6380 lock_output_stream(out);
6381 pthread_mutex_lock(&adev->lock);
6382
6383 ret = check_a2dp_restore_l(adev, out, restore);
6384
6385 pthread_mutex_unlock(&adev->lock);
6386 pthread_mutex_unlock(&out->lock);
6387 return ret;
6388}
6389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006390static int adev_open(const hw_module_t *module, const char *name,
6391 hw_device_t **device)
6392{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006393 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006394
Eric Laurent2bafff12016-03-17 12:17:23 -07006395 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006396 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006397 pthread_mutex_lock(&adev_init_lock);
6398 if (audio_device_ref_count != 0) {
6399 *device = &adev->device.common;
6400 audio_device_ref_count++;
6401 ALOGV("%s: returning existing instance of adev", __func__);
6402 ALOGV("%s: exit", __func__);
6403 pthread_mutex_unlock(&adev_init_lock);
6404 return 0;
6405 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406 adev = calloc(1, sizeof(struct audio_device));
6407
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006408 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006410 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6411 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6412 adev->device.common.module = (struct hw_module_t *)module;
6413 adev->device.common.close = adev_close;
6414
6415 adev->device.init_check = adev_init_check;
6416 adev->device.set_voice_volume = adev_set_voice_volume;
6417 adev->device.set_master_volume = adev_set_master_volume;
6418 adev->device.get_master_volume = adev_get_master_volume;
6419 adev->device.set_master_mute = adev_set_master_mute;
6420 adev->device.get_master_mute = adev_get_master_mute;
6421 adev->device.set_mode = adev_set_mode;
6422 adev->device.set_mic_mute = adev_set_mic_mute;
6423 adev->device.get_mic_mute = adev_get_mic_mute;
6424 adev->device.set_parameters = adev_set_parameters;
6425 adev->device.get_parameters = adev_get_parameters;
6426 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6427 adev->device.open_output_stream = adev_open_output_stream;
6428 adev->device.close_output_stream = adev_close_output_stream;
6429 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006431 adev->device.close_input_stream = adev_close_input_stream;
6432 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006433 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006434
6435 /* Set the default route before the PCM stream is opened */
6436 pthread_mutex_lock(&adev->lock);
6437 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006438 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006439 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006440 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006441 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006442 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006443 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006444 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006445 pthread_mutex_unlock(&adev->lock);
6446
6447 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006448 adev->platform = platform_init(adev);
6449 if (!adev->platform) {
6450 free(adev->snd_dev_ref_cnt);
6451 free(adev);
6452 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6453 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006454 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006455 return -EINVAL;
6456 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006457 adev->extspk = audio_extn_extspk_init(adev);
6458
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006459 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6460 if (adev->visualizer_lib == NULL) {
6461 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6462 } else {
6463 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6464 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006465 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006466 "visualizer_hal_start_output");
6467 adev->visualizer_stop_output =
6468 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6469 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006470 }
6471
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006472 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6473 if (adev->offload_effects_lib == NULL) {
6474 ALOGW("%s: DLOPEN failed for %s", __func__,
6475 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6476 } else {
6477 ALOGV("%s: DLOPEN successful for %s", __func__,
6478 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6479 adev->offload_effects_start_output =
6480 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6481 "offload_effects_bundle_hal_start_output");
6482 adev->offload_effects_stop_output =
6483 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6484 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006485 }
6486
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006487 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6488 if (adev->adm_lib == NULL) {
6489 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6490 } else {
6491 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6492 adev->adm_init = (adm_init_t)
6493 dlsym(adev->adm_lib, "adm_init");
6494 adev->adm_deinit = (adm_deinit_t)
6495 dlsym(adev->adm_lib, "adm_deinit");
6496 adev->adm_register_input_stream = (adm_register_input_stream_t)
6497 dlsym(adev->adm_lib, "adm_register_input_stream");
6498 adev->adm_register_output_stream = (adm_register_output_stream_t)
6499 dlsym(adev->adm_lib, "adm_register_output_stream");
6500 adev->adm_deregister_stream = (adm_deregister_stream_t)
6501 dlsym(adev->adm_lib, "adm_deregister_stream");
6502 adev->adm_request_focus = (adm_request_focus_t)
6503 dlsym(adev->adm_lib, "adm_request_focus");
6504 adev->adm_abandon_focus = (adm_abandon_focus_t)
6505 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006506 adev->adm_set_config = (adm_set_config_t)
6507 dlsym(adev->adm_lib, "adm_set_config");
6508 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6509 dlsym(adev->adm_lib, "adm_request_focus_v2");
6510 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6511 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6512 adev->adm_on_routing_change = (adm_on_routing_change_t)
6513 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006514 }
6515
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006516 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006517 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006518
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006519 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006520
Andy Hung31aca912014-03-20 17:14:59 -07006521 if (k_enable_extended_precision)
6522 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006523
Glenn Kasten4f993392014-05-14 07:30:48 -07006524 char value[PROPERTY_VALUE_MAX];
6525 int trial;
6526 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6527 trial = atoi(value);
6528 if (period_size_is_plausible_for_low_latency(trial)) {
6529 pcm_config_low_latency.period_size = trial;
6530 pcm_config_low_latency.start_threshold = trial / 4;
6531 pcm_config_low_latency.avail_min = trial / 4;
6532 configured_low_latency_capture_period_size = trial;
6533 }
6534 }
6535 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6536 trial = atoi(value);
6537 if (period_size_is_plausible_for_low_latency(trial)) {
6538 configured_low_latency_capture_period_size = trial;
6539 }
6540 }
6541
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006542 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6543
Eric Laurent5f4ca952018-10-19 17:33:43 -07006544 adev->camera_orientation = CAMERA_DEFAULT;
6545
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006546 // commented as full set of app type cfg is sent from platform
6547 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006548 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006549
6550 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6551 af_period_multiplier = atoi(value);
6552 if (af_period_multiplier < 0) {
6553 af_period_multiplier = 2;
6554 } else if (af_period_multiplier > 4) {
6555 af_period_multiplier = 4;
6556 }
6557 ALOGV("new period_multiplier = %d", af_period_multiplier);
6558 }
6559
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006560 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006561 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006562 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006563
vivek mehta1a9b7c02015-06-25 11:49:38 -07006564 pthread_mutex_unlock(&adev_init_lock);
6565
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006566 if (adev->adm_init)
6567 adev->adm_data = adev->adm_init();
6568
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006569 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006570 audio_extn_snd_mon_init();
6571 pthread_mutex_lock(&adev->lock);
6572 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6573 adev->card_status = CARD_STATUS_ONLINE;
6574 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006575 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006576
Eric Laurent2bafff12016-03-17 12:17:23 -07006577 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578 return 0;
6579}
6580
6581static struct hw_module_methods_t hal_module_methods = {
6582 .open = adev_open,
6583};
6584
6585struct audio_module HAL_MODULE_INFO_SYM = {
6586 .common = {
6587 .tag = HARDWARE_MODULE_TAG,
6588 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6589 .hal_api_version = HARDWARE_HAL_API_VERSION,
6590 .id = AUDIO_HARDWARE_MODULE_ID,
6591 .name = "QCOM Audio HAL",
6592 .author = "Code Aurora Forum",
6593 .methods = &hal_module_methods,
6594 },
6595};