blob: e0c2fce63d36186690773b566622a861a825c0e5 [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
Haynes Mathew George5191a852013-09-11 14:19:36 -0700347static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700348static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700349static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700350static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700351//cache last MBDRC cal step level
352static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700353
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800354static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
355static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
356
justinwengc6347db2019-02-21 18:49:00 +0800357static int in_set_microphone_direction(const struct audio_stream_in *stream,
358 audio_microphone_direction_t dir);
359static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
360
361
Haynes Mathew George03c40102016-01-29 17:57:48 -0800362static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
363 int flags __unused)
364{
365 int dir = 0;
366 switch (uc_id) {
367 case USECASE_AUDIO_RECORD_LOW_LATENCY:
368 dir = 1;
369 case USECASE_AUDIO_PLAYBACK_ULL:
370 break;
371 default:
372 return false;
373 }
374
375 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
376 PCM_PLAYBACK : PCM_CAPTURE);
377 if (adev->adm_is_noirq_avail)
378 return adev->adm_is_noirq_avail(adev->adm_data,
379 adev->snd_card, dev_id, dir);
380 return false;
381}
382
383static void register_out_stream(struct stream_out *out)
384{
385 struct audio_device *adev = out->dev;
386 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
387 return;
388
389 if (!adev->adm_register_output_stream)
390 return;
391
392 adev->adm_register_output_stream(adev->adm_data,
393 out->handle,
394 out->flags);
395
396 if (!adev->adm_set_config)
397 return;
398
399 if (out->realtime) {
400 adev->adm_set_config(adev->adm_data,
401 out->handle,
402 out->pcm, &out->config);
403 }
404}
405
406static void register_in_stream(struct stream_in *in)
407{
408 struct audio_device *adev = in->dev;
409 if (!adev->adm_register_input_stream)
410 return;
411
412 adev->adm_register_input_stream(adev->adm_data,
413 in->capture_handle,
414 in->flags);
415
416 if (!adev->adm_set_config)
417 return;
418
419 if (in->realtime) {
420 adev->adm_set_config(adev->adm_data,
421 in->capture_handle,
422 in->pcm,
423 &in->config);
424 }
425}
426
427static void request_out_focus(struct stream_out *out, long ns)
428{
429 struct audio_device *adev = out->dev;
430
Haynes Mathew George03c40102016-01-29 17:57:48 -0800431 if (adev->adm_request_focus_v2) {
432 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
433 } else if (adev->adm_request_focus) {
434 adev->adm_request_focus(adev->adm_data, out->handle);
435 }
436}
437
438static void request_in_focus(struct stream_in *in, long ns)
439{
440 struct audio_device *adev = in->dev;
441
Haynes Mathew George03c40102016-01-29 17:57:48 -0800442 if (adev->adm_request_focus_v2) {
443 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
444 } else if (adev->adm_request_focus) {
445 adev->adm_request_focus(adev->adm_data, in->capture_handle);
446 }
447}
448
449static void release_out_focus(struct stream_out *out, long ns __unused)
450{
451 struct audio_device *adev = out->dev;
452
453 if (adev->adm_abandon_focus)
454 adev->adm_abandon_focus(adev->adm_data, out->handle);
455}
456
457static void release_in_focus(struct stream_in *in, long ns __unused)
458{
459 struct audio_device *adev = in->dev;
460 if (adev->adm_abandon_focus)
461 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
462}
463
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700464static int parse_snd_card_status(struct str_parms * parms, int * card,
465 card_status_t * status)
466{
467 char value[32]={0};
468 char state[32]={0};
469
470 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
471
472 if (ret < 0)
473 return -1;
474
475 // sscanf should be okay as value is of max length 32.
476 // same as sizeof state.
477 if (sscanf(value, "%d,%s", card, state) < 2)
478 return -1;
479
480 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
481 CARD_STATUS_OFFLINE;
482 return 0;
483}
484
vivek mehta40125092017-08-21 18:48:51 -0700485// always call with adev lock held
486void send_gain_dep_calibration_l() {
487 if (last_known_cal_step >= 0)
488 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
489}
490
vivek mehta1a9b7c02015-06-25 11:49:38 -0700491__attribute__ ((visibility ("default")))
492bool audio_hw_send_gain_dep_calibration(int level) {
493 bool ret_val = false;
494 ALOGV("%s: enter ... ", __func__);
495
496 pthread_mutex_lock(&adev_init_lock);
497
498 if (adev != NULL && adev->platform != NULL) {
499 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700500 last_known_cal_step = level;
501 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700502 pthread_mutex_unlock(&adev->lock);
503 } else {
504 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
505 }
506
507 pthread_mutex_unlock(&adev_init_lock);
508
509 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
510 return ret_val;
511}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700512
jasmine cha270b7762018-03-30 15:41:33 +0800513#ifdef MAXXAUDIO_QDSP_ENABLED
514bool audio_hw_send_ma_parameter(int stream_type, float vol, bool active)
515{
516 bool ret = false;
517 ALOGV("%s: enter ...", __func__);
518
519 pthread_mutex_lock(&adev_init_lock);
520
521 if (adev != NULL && adev->platform != NULL) {
522 pthread_mutex_lock(&adev->lock);
523 ret = audio_extn_ma_set_state(adev, stream_type, vol, active);
524 pthread_mutex_unlock(&adev->lock);
525 }
526
527 pthread_mutex_unlock(&adev_init_lock);
528
529 ALOGV("%s: exit with ret %d", __func__, ret);
530 return ret;
531}
532#else
533#define audio_hw_send_ma_parameter(stream_type, vol, active) (0)
534#endif
535
vivek mehtaa8d7c922016-05-25 14:40:44 -0700536__attribute__ ((visibility ("default")))
537int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
538 int table_size) {
539 int ret_val = 0;
540 ALOGV("%s: enter ... ", __func__);
541
542 pthread_mutex_lock(&adev_init_lock);
543 if (adev == NULL) {
544 ALOGW("%s: adev is NULL .... ", __func__);
545 goto done;
546 }
547
548 pthread_mutex_lock(&adev->lock);
549 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
550 pthread_mutex_unlock(&adev->lock);
551done:
552 pthread_mutex_unlock(&adev_init_lock);
553 ALOGV("%s: exit ... ", __func__);
554 return ret_val;
555}
556
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700557static bool is_supported_format(audio_format_t format)
558{
Eric Laurent8251ac82014-07-23 11:00:25 -0700559 switch (format) {
560 case AUDIO_FORMAT_MP3:
561 case AUDIO_FORMAT_AAC_LC:
562 case AUDIO_FORMAT_AAC_HE_V1:
563 case AUDIO_FORMAT_AAC_HE_V2:
564 return true;
565 default:
566 break;
567 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700568 return false;
569}
570
juyuchenbe5c67e2018-08-29 17:19:20 +0800571static bool is_supported_24bits_audiosource(audio_source_t source)
572{
573 switch (source) {
574 case AUDIO_SOURCE_UNPROCESSED:
575#ifdef ENABLED_24BITS_CAMCORDER
576 case AUDIO_SOURCE_CAMCORDER:
577#endif
578 return true;
579 default:
580 break;
581 }
582 return false;
583}
584
Haynes Mathew George03c40102016-01-29 17:57:48 -0800585static inline bool is_mmap_usecase(audio_usecase_t uc_id)
586{
587 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
588 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
589}
590
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700591static int get_snd_codec_id(audio_format_t format)
592{
593 int id = 0;
594
Eric Laurent8251ac82014-07-23 11:00:25 -0700595 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700596 case AUDIO_FORMAT_MP3:
597 id = SND_AUDIOCODEC_MP3;
598 break;
599 case AUDIO_FORMAT_AAC:
600 id = SND_AUDIOCODEC_AAC;
601 break;
602 default:
603 ALOGE("%s: Unsupported audio format", __func__);
604 }
605
606 return id;
607}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800608
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800609static int audio_ssr_status(struct audio_device *adev)
610{
611 int ret = 0;
612 struct mixer_ctl *ctl;
613 const char *mixer_ctl_name = "Audio SSR Status";
614
615 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
616 ret = mixer_ctl_get_value(ctl, 0);
617 ALOGD("%s: value: %d", __func__, ret);
618 return ret;
619}
620
vivek mehta4a824772017-06-08 19:05:49 -0700621static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
622{
623 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
624}
625
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800626static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
627{
628 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
629 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
630 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
631 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
632 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
633 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
634
635}
636
637static bool is_a2dp_device(snd_device_t out_snd_device)
638{
639 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
640}
641
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800642int enable_audio_route(struct audio_device *adev,
643 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800644{
yixuanjiang509f0a72018-09-06 18:37:23 +0800645 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700646 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800647
648 if (usecase == NULL)
649 return -EINVAL;
650
651 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
652
yixuanjiang509f0a72018-09-06 18:37:23 +0800653 if (usecase->type == PCM_CAPTURE)
654 snd_device = usecase->in_snd_device;
655 else
656 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530657 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Chafb2ea2c2019-03-04 18:12:47 +0800658 audio_extn_ma_set_device(usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800659 audio_extn_utils_send_audio_calibration(adev, usecase);
Andy Hung11f10e22018-10-19 17:47:12 -0700660
661 // we shouldn't truncate mixer_path
662 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
663 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
664 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800665 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Andy Hung11f10e22018-10-19 17:47:12 -0700666
yixuanjiang509f0a72018-09-06 18:37:23 +0800667 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700668 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700669 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800671 ALOGV("%s: exit", __func__);
672 return 0;
673}
674
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800675int disable_audio_route(struct audio_device *adev,
676 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800677{
yixuanjiang509f0a72018-09-06 18:37:23 +0800678 snd_device_t snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700679 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800680
681 if (usecase == NULL)
682 return -EINVAL;
683
684 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
yixuanjiang509f0a72018-09-06 18:37:23 +0800685 if (usecase->type == PCM_CAPTURE)
686 snd_device = usecase->in_snd_device;
687 else
688 snd_device = usecase->out_snd_device;
Andy Hung11f10e22018-10-19 17:47:12 -0700689
690 // we shouldn't truncate mixer_path
691 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
692 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
693 // this also appends to mixer_path
yixuanjiang509f0a72018-09-06 18:37:23 +0800694 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700695 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Andy Hung11f10e22018-10-19 17:47:12 -0700696
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700697 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000698 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800699
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700 ALOGV("%s: exit", __func__);
701 return 0;
702}
703
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800704int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700705 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800706{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700707 int i, num_devices = 0;
708 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800709 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800710 if (snd_device < SND_DEVICE_MIN ||
711 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800712 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800713 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800714 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700716 platform_send_audio_calibration(adev->platform, snd_device);
717
vivek mehtade4849c2016-03-03 17:23:38 -0800718 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700719 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700720 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800721 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 }
723
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700724 /* due to the possibility of calibration overwrite between listen
725 and audio, notify sound trigger hal before audio calibration is sent */
726 audio_extn_sound_trigger_update_device_status(snd_device,
727 ST_EVENT_SND_DEVICE_BUSY);
728
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700729 if (audio_extn_spkr_prot_is_enabled())
730 audio_extn_spkr_prot_calib_cancel(adev);
731
zhaoyang yin4211fad2015-06-04 21:13:25 +0800732 audio_extn_dsm_feedback_enable(adev, snd_device, true);
733
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700734 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800735 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
juyuchen1d05ba32018-03-31 16:03:51 +0800736 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700737 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
738 audio_extn_spkr_prot_is_enabled()) {
Aniket Kumar Lata9d6679a2018-04-11 18:13:23 -0700739 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800740 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700741 }
742 if (audio_extn_spkr_prot_start_processing(snd_device)) {
743 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800744 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700745 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700746 } else if (platform_can_split_snd_device(snd_device,
747 &num_devices,
748 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700749 for (i = 0; i < num_devices; i++) {
750 enable_snd_device(adev, new_snd_devices[i]);
751 }
vivek mehtab6506412015-08-07 16:55:17 -0700752 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700753 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800754 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
755 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
756 ALOGE(" %s: Invalid sound device returned", __func__);
757 goto on_error;
758 }
Ed Tam70b5c142016-03-21 19:14:29 -0700759
Eric Laurent2e140aa2016-06-30 17:14:46 -0700760 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Aniket Kumar Lataa158e862018-05-11 17:28:40 -0700761
762 if (is_a2dp_device(snd_device) &&
763 (audio_extn_a2dp_start_playback() < 0)) {
764 ALOGE("%s: failed to configure A2DP control path", __func__);
765 goto on_error;
766 }
767
vivek mehtade4849c2016-03-03 17:23:38 -0800768 audio_route_apply_and_update_path(adev->audio_route, device_name);
769 }
770on_success:
771 adev->snd_dev_ref_cnt[snd_device]++;
772 ret_val = 0;
773on_error:
774 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800775}
776
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800777int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700778 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700780 int i, num_devices = 0;
781 snd_device_t new_snd_devices[2];
782
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800783 if (snd_device < SND_DEVICE_MIN ||
784 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800785 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800786 return -EINVAL;
787 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700788 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
789 ALOGE("%s: device ref cnt is already 0", __func__);
790 return -EINVAL;
791 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800792 audio_extn_tfa_98xx_disable_speaker(snd_device);
793
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794 adev->snd_dev_ref_cnt[snd_device]--;
795 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800796 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800797
798 if (is_a2dp_device(snd_device))
799 audio_extn_a2dp_stop_playback();
800
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700801 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800802 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700803 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700804 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
805 audio_extn_spkr_prot_is_enabled()) {
806 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700807
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700808 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
809 // and does not use speaker swap. As this code causes a problem with device enable ref
810 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700811 // when speaker device is disabled, reset swap.
812 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700813 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700814
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700815 } else if (platform_can_split_snd_device(snd_device,
816 &num_devices,
817 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818 for (i = 0; i < num_devices; i++) {
819 disable_snd_device(adev, new_snd_devices[i]);
820 }
vivek mehtab6506412015-08-07 16:55:17 -0700821 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700822 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800823 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
824 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
825 ALOGE(" %s: Invalid sound device returned", __func__);
826 return -EINVAL;
827 }
828
Eric Laurent2e140aa2016-06-30 17:14:46 -0700829 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800830 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700831 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700832 audio_extn_sound_trigger_update_device_status(snd_device,
833 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 }
vivek mehtab6506412015-08-07 16:55:17 -0700835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836 return 0;
837}
838
Vignesh Kulothungan64698822018-01-23 11:25:18 -0800839#ifdef DYNAMIC_ECNS_ENABLED
840static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
841 struct stream_in *in,
842 struct audio_effect_config effect_config,
843 unsigned int param_value)
844{
845 char mixer_ctl_name[] = "Audio Effect";
846 long set_values[6];
847
848 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
849 if (!ctl) {
850 ALOGE("%s: Could not get mixer ctl - %s",
851 __func__, mixer_ctl_name);
852 return -EINVAL;
853 }
854
855 set_values[0] = 1; //0:Rx 1:Tx
856 set_values[1] = in->app_type_cfg.app_type;
857 set_values[2] = (long)effect_config.module_id;
858 set_values[3] = (long)effect_config.instance_id;
859 set_values[4] = (long)effect_config.param_id;
860 set_values[5] = param_value;
861
862 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
863
864 return 0;
865
866}
867
868static int update_effect_param_ecns(struct audio_usecase *usecase,
869 unsigned int module_id, int effect_type,
870 unsigned int *param_value)
871{
872 int ret = 0;
873 struct audio_effect_config other_effect_config;
874 struct stream_in *in = NULL;
875
876 if (!usecase)
877 return -EINVAL;
878
879 in = usecase->stream.in;
880
881 /* Get the effect config data of the other effect */
882 ret = platform_get_effect_config_data(usecase->in_snd_device,
883 &other_effect_config,
884 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
885 if (ret < 0) {
886 ALOGE("%s Failed to get effect params %d", __func__, ret);
887 return ret;
888 }
889
890 if (module_id == other_effect_config.module_id) {
891 //Same module id for AEC/NS. Values need to be combined
892 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
893 ((effect_type == EFFECT_NS) && (in->enable_aec)))
894 *param_value |= other_effect_config.param_value;
895 }
896
897 return ret;
898}
899
900static int enable_disable_effect(struct audio_device *adev, struct stream_in *in,
901 int effect_type, bool enable)
902{
903 struct audio_effect_config effect_config;
904 struct audio_usecase *usecase = NULL;
905 int ret = 0;
906 unsigned int param_value = 0;
907
908 if (!in) {
909 ALOGE("%s: Invalid input stream", __func__);
910 return -EINVAL;
911 }
912
913 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
914
915 usecase = get_usecase_from_list(adev, in->usecase);
916
917 ret = platform_get_effect_config_data(usecase->in_snd_device,
918 &effect_config, effect_type);
919 if (ret < 0) {
920 ALOGE("%s Failed to get module id %d", __func__, ret);
921 return ret;
922 }
923 ALOGV("%s: module %d app_type %d usecase->id:%d usecase->in_snd_device:%d",
924 __func__, effect_config.module_id, in->app_type_cfg.app_type,
925 usecase->id, usecase->in_snd_device);
926
927 if (enable)
928 param_value = effect_config.param_value;
929
930 /*Special handling for AEC & NS effects Param values need to be
931 updated if module ids are same*/
932
933 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
934 ret = update_effect_param_ecns(usecase, effect_config.module_id,
935 effect_type, &param_value);
936 if (ret < 0)
937 return ret;
938 }
939
940 ret = send_effect_enable_disable_mixer_ctl(adev, in,
941 effect_config, param_value);
942
943 return ret;
944}
945
946static int check_and_enable_effect(struct audio_device *adev)
947{
948 int ret = 0;
949
950 struct listnode *node;
951 struct stream_in *in = NULL;
952
953 list_for_each(node, &adev->usecase_list)
954 {
955 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
956 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
957 in = usecase->stream.in;
958
959 if (in->standby)
960 continue;
961
962 if (in->enable_aec) {
963 ret = enable_disable_effect(adev, in, EFFECT_AEC, true);
964 }
965
966 if (in->enable_ns &&
967 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
968 ret = enable_disable_effect(adev, in, EFFECT_NS, true);
969 }
970 }
971 }
972
973 return ret;
974}
975#else
976#define enable_disable_effect(w, x, y, z) -ENOSYS
977#define check_and_enable_effect(x) -ENOSYS
978#endif
979
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700980/*
981 legend:
982 uc - existing usecase
983 new_uc - new usecase
984 d1, d11, d2 - SND_DEVICE enums
985 a1, a2 - corresponding ANDROID device enums
986 B, B1, B2 - backend strings
987
988case 1
989 uc->dev d1 (a1) B1
990 new_uc->dev d1 (a1), d2 (a2) B1, B2
991
992 resolution: disable and enable uc->dev on d1
993
994case 2
995 uc->dev d1 (a1) B1
996 new_uc->dev d11 (a1) B1
997
998 resolution: need to switch uc since d1 and d11 are related
999 (e.g. speaker and voice-speaker)
1000 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1001
1002case 3
1003 uc->dev d1 (a1) B1
1004 new_uc->dev d2 (a2) B2
1005
1006 resolution: no need to switch uc
1007
1008case 4
1009 uc->dev d1 (a1) B
1010 new_uc->dev d2 (a2) B
1011
1012 resolution: disable enable uc-dev on d2 since backends match
1013 we cannot enable two streams on two different devices if they
1014 share the same backend. e.g. if offload is on speaker device using
1015 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1016 using the same backend, offload must also be switched to voice-handset.
1017
1018case 5
1019 uc->dev d1 (a1) B
1020 new_uc->dev d1 (a1), d2 (a2) B
1021
1022 resolution: disable enable uc-dev on d2 since backends match
1023 we cannot enable two streams on two different devices if they
1024 share the same backend.
1025
1026case 6
1027 uc->dev d1 a1 B1
1028 new_uc->dev d2 a1 B2
1029
1030 resolution: no need to switch
1031
1032case 7
1033
1034 uc->dev d1 (a1), d2 (a2) B1, B2
1035 new_uc->dev d1 B1
1036
1037 resolution: no need to switch
1038
1039*/
1040static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
1041 struct audio_usecase *new_uc,
1042 snd_device_t new_snd_device)
1043{
1044 audio_devices_t a1 = uc->stream.out->devices;
1045 audio_devices_t a2 = new_uc->stream.out->devices;
1046
1047 snd_device_t d1 = uc->out_snd_device;
1048 snd_device_t d2 = new_snd_device;
1049
1050 // Treat as a special case when a1 and a2 are not disjoint
1051 if ((a1 != a2) && (a1 & a2)) {
1052 snd_device_t d3[2];
1053 int num_devices = 0;
1054 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
1055 &num_devices,
1056 d3);
1057 if (ret < 0) {
1058 if (ret != -ENOSYS) {
1059 ALOGW("%s failed to split snd_device %d",
1060 __func__,
1061 popcount(a1) > 1 ? d1 : d2);
1062 }
1063 goto end;
1064 }
1065
1066 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1067 // But if it does happen, we need to give priority to d2 if
1068 // the combo devices active on the existing usecase share a backend.
1069 // This is because we cannot have a usecase active on a combo device
1070 // and a new usecase requests one device in this combo pair.
1071 if (platform_check_backends_match(d3[0], d3[1])) {
1072 return d2; // case 5
1073 } else {
1074 return d1; // case 1
1075 }
1076 } else {
1077 if (platform_check_backends_match(d1, d2)) {
1078 return d2; // case 2, 4
1079 } else {
1080 return d1; // case 6, 3
1081 }
1082 }
1083
1084end:
1085 return d2; // return whatever was calculated before.
1086}
1087
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001088static void check_and_route_playback_usecases(struct audio_device *adev,
1089 struct audio_usecase *uc_info,
1090 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001091{
1092 struct listnode *node;
1093 struct audio_usecase *usecase;
1094 bool switch_device[AUDIO_USECASE_MAX];
1095 int i, num_uc_to_switch = 0;
1096
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001097 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
1098 uc_info,
1099 snd_device);
David Linee3fe402017-03-13 10:00:42 -07001100
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001101 /* For a2dp device reconfigure all active sessions
1102 * with new AFE encoder format based on a2dp state
1103 */
1104 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001105 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device ||
1106 SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP == snd_device) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001107 audio_extn_a2dp_is_force_device_switch()) {
1108 force_routing = true;
1109 }
1110
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001111 /*
1112 * This function is to make sure that all the usecases that are active on
1113 * the hardware codec backend are always routed to any one device that is
1114 * handled by the hardware codec.
1115 * For example, if low-latency and deep-buffer usecases are currently active
1116 * on speaker and out_set_parameters(headset) is received on low-latency
1117 * output, then we have to make sure deep-buffer is also switched to headset,
1118 * because of the limitation that both the devices cannot be enabled
1119 * at the same time as they share the same backend.
1120 */
1121 /* Disable all the usecases on the shared backend other than the
1122 specified usecase */
1123 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1124 switch_device[i] = false;
1125
1126 list_for_each(node, &adev->usecase_list) {
1127 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001128 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
1129 continue;
1130
1131 if (force_routing ||
1132 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -07001133 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
1134 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -07001135 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1137 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -07001138 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001139 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 switch_device[usecase->id] = true;
1141 num_uc_to_switch++;
1142 }
1143 }
1144
1145 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001146 list_for_each(node, &adev->usecase_list) {
1147 usecase = node_to_item(node, struct audio_usecase, list);
1148 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001149 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001150 }
1151 }
1152
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001153 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +09001154 list_for_each(node, &adev->usecase_list) {
1155 usecase = node_to_item(node, struct audio_usecase, list);
1156 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -07001157 d_device = derive_playback_snd_device(usecase, uc_info,
1158 snd_device);
1159 enable_snd_device(adev, d_device);
1160 /* Update the out_snd_device before enabling the audio route */
1161 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 }
1163 }
1164
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 /* Re-route all the usecases on the shared backend other than the
1166 specified usecase to new snd devices */
1167 list_for_each(node, &adev->usecase_list) {
1168 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001170 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 }
1172 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 }
1174}
1175
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001176static void check_and_route_capture_usecases(struct audio_device *adev,
1177 struct audio_usecase *uc_info,
1178 snd_device_t snd_device)
1179{
1180 struct listnode *node;
1181 struct audio_usecase *usecase;
1182 bool switch_device[AUDIO_USECASE_MAX];
1183 int i, num_uc_to_switch = 0;
1184
vivek mehta4ed66e62016-04-15 23:33:34 -07001185 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
1186
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001187 /*
1188 * This function is to make sure that all the active capture usecases
1189 * are always routed to the same input sound device.
1190 * For example, if audio-record and voice-call usecases are currently
1191 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1192 * is received for voice call then we have to make sure that audio-record
1193 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1194 * because of the limitation that two devices cannot be enabled
1195 * at the same time if they share the same backend.
1196 */
1197 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1198 switch_device[i] = false;
1199
1200 list_for_each(node, &adev->usecase_list) {
1201 usecase = node_to_item(node, struct audio_usecase, list);
1202 if (usecase->type != PCM_PLAYBACK &&
1203 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -07001204 usecase->in_snd_device != snd_device &&
Carter Hsu0a1160c2018-10-04 09:24:36 +08001205 ((uc_info->type == VOICE_CALL &&
1206 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1207 platform_check_backends_match(snd_device,\
1208 usecase->in_snd_device)) &&
Anish Kumarff864712015-06-03 13:35:11 -07001209 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1211 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001212 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001213 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001214 switch_device[usecase->id] = true;
1215 num_uc_to_switch++;
1216 }
1217 }
1218
1219 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001220 list_for_each(node, &adev->usecase_list) {
1221 usecase = node_to_item(node, struct audio_usecase, list);
1222 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001223 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001224 }
1225 }
1226
1227 list_for_each(node, &adev->usecase_list) {
1228 usecase = node_to_item(node, struct audio_usecase, list);
1229 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001230 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001231 }
1232 }
1233
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001234 /* Re-route all the usecases on the shared backend other than the
1235 specified usecase to new snd devices */
1236 list_for_each(node, &adev->usecase_list) {
1237 usecase = node_to_item(node, struct audio_usecase, list);
1238 /* Update the in_snd_device only before enabling the audio route */
1239 if (switch_device[usecase->id] ) {
1240 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001241 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001242 }
1243 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001244 }
1245}
1246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001248static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001250 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001251 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
1253 switch (channels) {
1254 /*
1255 * Do not handle stereo output in Multi-channel cases
1256 * Stereo case is handled in normal playback path
1257 */
1258 case 6:
1259 ALOGV("%s: HDMI supports 5.1", __func__);
1260 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1261 break;
1262 case 8:
1263 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1264 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1265 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1266 break;
1267 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001268 ALOGE("HDMI does not support multi channel playback");
1269 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 break;
1271 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001272 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273}
1274
Andy Hung18859412017-08-09 11:47:21 -07001275static ssize_t read_usb_sup_sample_rates(bool is_playback,
1276 uint32_t *supported_sample_rates,
1277 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001278{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001279 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1280 supported_sample_rates,
1281 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001282#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001283 for (ssize_t i=0; i<count; i++) {
1284 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1285 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001286 }
1287#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001288 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001289}
1290
Haynes Mathew George569b7482017-05-08 14:44:27 -07001291static int read_usb_sup_channel_masks(bool is_playback,
1292 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001293 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001294{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001295 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001296 int channel_count;
1297 uint32_t num_masks = 0;
1298 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1299 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001300 }
Eric Laurent74b55762017-07-09 17:04:53 -07001301 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001302 // start from 2 channels as framework currently doesn't support mono.
Eric Laurent154055d2019-05-01 18:07:29 -07001303 if (channels >= FCC_2) {
1304 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
Eric Laurent74b55762017-07-09 17:04:53 -07001305 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001306 for (channel_count = FCC_2;
1307 channel_count <= channels && num_masks < max_masks;
1308 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001309 supported_channel_masks[num_masks++] =
1310 audio_channel_mask_for_index_assignment_from_count(channel_count);
1311 }
1312 } else {
1313 // For capture we report all supported channel masks from 1 channel up.
1314 channel_count = MIN_CHANNEL_COUNT;
1315 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1316 // indexed mask
1317 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
Eric Laurent154055d2019-05-01 18:07:29 -07001318 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1319 if (channel_count <= FCC_2) {
1320 mask = audio_channel_in_mask_from_count(channel_count);
1321 supported_channel_masks[num_masks++] = mask;
1322 }
Andy Hung88ce1d92018-10-29 18:31:12 -07001323 const audio_channel_mask_t index_mask =
1324 audio_channel_mask_for_index_assignment_from_count(channel_count);
1325 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1326 supported_channel_masks[num_masks++] = index_mask;
1327 }
Eric Laurent74b55762017-07-09 17:04:53 -07001328 }
1329 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001330#ifdef NDEBUG
1331 for (size_t i = 0; i < num_masks; ++i) {
1332 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1333 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1334 }
1335#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001336 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001337}
1338
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001339static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001340 audio_format_t *supported_formats,
1341 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001342{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001343 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001344 switch (bitwidth) {
1345 case 24:
1346 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001347 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001348 break;
1349 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001350 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001351 break;
1352 case 16:
1353 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001354 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001355 break;
1356 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001357 ALOGV("%s: %s supported format %d", __func__,
1358 is_playback ? "P" : "C", bitwidth);
1359 return 1;
1360}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001361
Haynes Mathew George569b7482017-05-08 14:44:27 -07001362static int read_usb_sup_params_and_compare(bool is_playback,
1363 audio_format_t *format,
1364 audio_format_t *supported_formats,
1365 uint32_t max_formats,
1366 audio_channel_mask_t *mask,
1367 audio_channel_mask_t *supported_channel_masks,
1368 uint32_t max_masks,
1369 uint32_t *rate,
1370 uint32_t *supported_sample_rates,
1371 uint32_t max_rates) {
1372 int ret = 0;
1373 int num_formats;
1374 int num_masks;
1375 int num_rates;
1376 int i;
1377
1378 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1379 max_formats);
1380 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1381 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001382
Haynes Mathew George569b7482017-05-08 14:44:27 -07001383 num_rates = read_usb_sup_sample_rates(is_playback,
1384 supported_sample_rates, max_rates);
1385
1386#define LUT(table, len, what, dflt) \
1387 for (i=0; i<len && (table[i] != what); i++); \
1388 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1389
1390 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1391 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1392 LUT(supported_sample_rates, num_rates, *rate, 0);
1393
1394#undef LUT
1395 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001396}
1397
Andy Hungd9653bd2017-08-01 19:31:39 -07001398static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1399{
1400 // Check if usb is ready.
1401 // The usb device may have been removed quickly after insertion and hence
1402 // no longer available. This will show up as empty channel masks, or rates.
1403
1404 pthread_mutex_lock(&adev->lock);
1405 uint32_t supported_sample_rate;
1406
1407 // we consider usb ready if we can fetch at least one sample rate.
1408 const bool ready = read_usb_sup_sample_rates(
1409 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1410 pthread_mutex_unlock(&adev->lock);
1411 return ready;
1412}
1413
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001414static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1415{
1416 struct audio_usecase *usecase;
1417 struct listnode *node;
1418
1419 list_for_each(node, &adev->usecase_list) {
1420 usecase = node_to_item(node, struct audio_usecase, list);
1421 if (usecase->type == VOICE_CALL) {
1422 ALOGV("%s: usecase id %d", __func__, usecase->id);
1423 return usecase->id;
1424 }
1425 }
1426 return USECASE_INVALID;
1427}
1428
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001429struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1430 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001431{
1432 struct audio_usecase *usecase;
1433 struct listnode *node;
1434
1435 list_for_each(node, &adev->usecase_list) {
1436 usecase = node_to_item(node, struct audio_usecase, list);
1437 if (usecase->id == uc_id)
1438 return usecase;
1439 }
1440 return NULL;
1441}
1442
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001443static bool force_device_switch(struct audio_usecase *usecase)
1444{
1445 if (usecase->stream.out == NULL) {
1446 ALOGE("%s: stream.out is NULL", __func__);
1447 return false;
1448 }
1449
1450 // Force all A2DP output devices to reconfigure for proper AFE encode format
1451 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1452 // in suspended state, hence try to trigger a retry when we again get a routing request.
1453 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1454 audio_extn_a2dp_is_force_device_switch()) {
1455 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1456 return true;
1457 }
1458
1459 return false;
1460}
1461
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001462struct stream_in *adev_get_active_input(const struct audio_device *adev)
1463{
1464 struct listnode *node;
1465 struct stream_in *last_active_in = NULL;
1466
1467 /* Get last added active input.
1468 * TODO: We may use a priority mechanism to pick highest priority active source */
1469 list_for_each(node, &adev->usecase_list)
1470 {
1471 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1472 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
1473 last_active_in = usecase->stream.in;
1474 }
1475 }
1476
1477 return last_active_in;
1478}
1479
1480struct stream_in *get_voice_communication_input(const struct audio_device *adev)
1481{
1482 struct listnode *node;
1483
1484 /* First check active inputs with voice communication source and then
1485 * any input if audio mode is in communication */
1486 list_for_each(node, &adev->usecase_list)
1487 {
1488 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
1489 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
1490 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1491 return usecase->stream.in;
1492 }
1493 }
1494 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
1495 return adev_get_active_input(adev);
1496 }
1497 return NULL;
1498}
1499
HW Leef88584d2019-03-18 17:27:18 +08001500int select_devices_with_force_switch(struct audio_device *adev,
1501 audio_usecase_t uc_id,
1502 bool force_switch)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001504 snd_device_t out_snd_device = SND_DEVICE_NONE;
1505 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001506 struct audio_usecase *usecase = NULL;
1507 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001508 struct audio_usecase *hfp_usecase = NULL;
1509 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001510 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001511 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001512 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1513 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001514
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515 usecase = get_usecase_from_list(adev, uc_id);
1516 if (usecase == NULL) {
1517 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1518 return -EINVAL;
1519 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001521 if ((usecase->type == VOICE_CALL) ||
1522 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001523 out_snd_device = platform_get_output_snd_device(adev->platform,
1524 usecase->stream.out->devices);
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001525 in_snd_device = platform_get_input_snd_device(adev->platform,
1526 NULL,
1527 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001528 usecase->devices = usecase->stream.out->devices;
1529 } else {
1530 /*
1531 * If the voice call is active, use the sound devices of voice call usecase
1532 * so that it would not result any device switch. All the usecases will
1533 * be switched to new device when select_devices() is called for voice call
1534 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001535 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001537 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001538 vc_usecase = get_usecase_from_list(adev,
1539 get_voice_usecase_id_from_list(adev));
1540 if ((vc_usecase != NULL) &&
1541 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
juyuchend194b432018-11-16 14:15:16 +08001542 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
1543 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001544 in_snd_device = vc_usecase->in_snd_device;
1545 out_snd_device = vc_usecase->out_snd_device;
1546 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001547 } else if (audio_extn_hfp_is_active(adev)) {
1548 hfp_ucid = audio_extn_hfp_get_usecase();
1549 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1550 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1551 in_snd_device = hfp_usecase->in_snd_device;
1552 out_snd_device = hfp_usecase->out_snd_device;
1553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 }
1555 if (usecase->type == PCM_PLAYBACK) {
1556 usecase->devices = usecase->stream.out->devices;
1557 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001558 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001559 struct stream_out *voip_out = adev->primary_output;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001560 struct stream_in *voip_in = get_voice_communication_input(adev);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001561
Eric Laurentb23d5282013-05-14 15:27:20 -07001562 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001564
1565 if (voip_usecase)
1566 voip_out = voip_usecase->stream.out;
1567
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001568 if (usecase->stream.out == voip_out && voip_in != NULL) {
1569 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001570 }
1571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 } else if (usecase->type == PCM_CAPTURE) {
1573 usecase->devices = usecase->stream.in->device;
1574 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001575 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001576 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001577 struct stream_in *voip_in = get_voice_communication_input(adev);
1578
1579 if (voip_in != NULL) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001580
1581 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1582 USECASE_AUDIO_PLAYBACK_VOIP);
1583
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001584 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001585 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1586 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001587 } else if (voip_usecase) {
1588 out_device = voip_usecase->stream.out->devices;
juyuchend194b432018-11-16 14:15:16 +08001589 } else if (adev->primary_output &&
1590 !adev->primary_output->standby) {
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001591 out_device = adev->primary_output->devices;
juyuchend194b432018-11-16 14:15:16 +08001592 } else {
1593 /* forcing speaker o/p device to get matching i/p pair
1594 in case o/p is not routed from same primary HAL */
1595 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001596 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001597 }
Eric Laurentd1b7a9b2018-11-15 12:24:31 -08001598 in_snd_device = platform_get_input_snd_device(adev->platform,
1599 usecase->stream.in,
1600 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001601 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001602 }
1603 }
1604
1605 if (out_snd_device == usecase->out_snd_device &&
1606 in_snd_device == usecase->in_snd_device) {
HW Leef88584d2019-03-18 17:27:18 +08001607 if (!force_device_switch(usecase) && !force_switch)
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001608 return 0;
1609 }
1610
1611 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1612 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1613 return 0;
1614 }
1615
Aniket Kumar Lata9723a962018-05-16 17:41:55 -07001616 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
1617 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001618 (!audio_extn_a2dp_is_ready())) {
1619 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
juyuchen9baad392018-06-05 19:02:10 +08001620 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
1621 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
1622 else
1623 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 }
1625
juyuchen66c4ecf2018-08-06 15:39:34 +08001626 if (usecase->id == USECASE_INCALL_MUSIC_UPLINK) {
1627 out_snd_device = SND_DEVICE_OUT_VOICE_MUSIC_TX;
1628 }
1629
Eric Laurent2bafff12016-03-17 12:17:23 -07001630 if (out_snd_device != SND_DEVICE_NONE &&
1631 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1632 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1633 __func__,
1634 use_case_table[uc_id],
1635 adev->last_logged_snd_device[uc_id][0],
1636 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1637 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1638 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1639 -1,
1640 out_snd_device,
1641 platform_get_snd_device_name(out_snd_device),
1642 platform_get_snd_device_acdb_id(out_snd_device));
1643 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1644 }
1645 if (in_snd_device != SND_DEVICE_NONE &&
1646 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1647 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1648 __func__,
1649 use_case_table[uc_id],
1650 adev->last_logged_snd_device[uc_id][1],
1651 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1652 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1653 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1654 -1,
1655 in_snd_device,
1656 platform_get_snd_device_name(in_snd_device),
1657 platform_get_snd_device_acdb_id(in_snd_device));
1658 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1659 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661 /*
1662 * Limitation: While in call, to do a device switch we need to disable
1663 * and enable both RX and TX devices though one of them is same as current
1664 * device.
1665 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001666 if ((usecase->type == VOICE_CALL) &&
1667 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1668 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001669 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001670 /* Disable sidetone only if voice call already exists */
1671 if (voice_is_call_state_active(adev))
1672 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001673 }
1674
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 /* Disable current sound devices */
1676 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001677 disable_audio_route(adev, usecase);
1678 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679 }
1680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001681 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001682 disable_audio_route(adev, usecase);
1683 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684 }
1685
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001686 /* Applicable only on the targets that has external modem.
1687 * New device information should be sent to modem before enabling
1688 * the devices to reduce in-call device switch time.
1689 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001690 if ((usecase->type == VOICE_CALL) &&
1691 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1692 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001693 status = platform_switch_voice_call_enable_device_config(adev->platform,
1694 out_snd_device,
1695 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001696 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001697
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001698 /* Enable new sound devices */
1699 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001700 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001701 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1702 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001703 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001704 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705 }
1706
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001707 if (in_snd_device != SND_DEVICE_NONE) {
1708 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001709 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001710 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711
Eric Laurentb23d5282013-05-14 15:27:20 -07001712 if (usecase->type == VOICE_CALL)
1713 status = platform_switch_voice_call_device_post(adev->platform,
1714 out_snd_device,
1715 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001716
sangwoo170731f2013-06-08 15:36:36 +09001717 usecase->in_snd_device = in_snd_device;
1718 usecase->out_snd_device = out_snd_device;
1719
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001720 audio_extn_tfa_98xx_set_mode();
1721
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001722 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001723
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001724 /* If input stream is already running the effect needs to be
1725 applied on the new input device that's being enabled here. */
1726 if (in_snd_device != SND_DEVICE_NONE)
1727 check_and_enable_effect(adev);
1728
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001729 /* Applicable only on the targets that has external modem.
1730 * Enable device command should be sent to modem only after
1731 * enabling voice call mixer controls
1732 */
vivek mehta765eb642015-08-07 19:46:06 -07001733 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001734 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1735 out_snd_device,
1736 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001737 /* Enable sidetone only if voice call already exists */
1738 if (voice_is_call_state_active(adev))
1739 voice_set_sidetone(adev, out_snd_device, true);
1740 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001741
Yung Ti Sue9d64f92018-06-22 17:38:47 +08001742 if (usecase->type != PCM_CAPTURE && voip_usecase) {
Eric Laurentf4520b02017-09-20 18:31:58 -07001743 struct stream_out *voip_out = voip_usecase->stream.out;
1744 audio_extn_utils_send_app_type_gain(adev,
1745 voip_out->app_type_cfg.app_type,
1746 &voip_out->app_type_cfg.gain[0]);
1747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 return status;
1749}
1750
HW Leef88584d2019-03-18 17:27:18 +08001751int select_devices(struct audio_device *adev,
1752 audio_usecase_t uc_id)
1753{
1754 return select_devices_with_force_switch(adev, uc_id, false);
1755}
1756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757static int stop_input_stream(struct stream_in *in)
1758{
1759 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 struct audio_usecase *uc_info;
1761 struct audio_device *adev = in->dev;
1762
Eric Laurent994a6932013-07-17 11:51:42 -07001763 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001764 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 uc_info = get_usecase_from_list(adev, in->usecase);
1767 if (uc_info == NULL) {
1768 ALOGE("%s: Could not find the usecase (%d) in the list",
1769 __func__, in->usecase);
1770 return -EINVAL;
1771 }
1772
vivek mehta781065c2017-04-04 12:55:01 -07001773 /* Close in-call recording streams */
1774 voice_check_and_stop_incall_rec_usecase(adev, in);
1775
Eric Laurent150dbfe2013-02-27 14:31:02 -08001776 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001777 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001778
1779 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001780 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001782 list_remove(&uc_info->list);
1783 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784
Eric Laurent994a6932013-07-17 11:51:42 -07001785 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 return ret;
1787}
1788
1789int start_input_stream(struct stream_in *in)
1790{
1791 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001792 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 struct audio_usecase *uc_info;
1794 struct audio_device *adev = in->dev;
1795
Eric Laurent994a6932013-07-17 11:51:42 -07001796 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001797
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001798 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1799 return -EIO;
1800
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001801 if (in->card_status == CARD_STATUS_OFFLINE ||
1802 adev->card_status == CARD_STATUS_OFFLINE) {
1803 ALOGW("in->card_status or adev->card_status offline, try again");
1804 ret = -EAGAIN;
1805 goto error_config;
1806 }
1807
vivek mehta781065c2017-04-04 12:55:01 -07001808 /* Check if source matches incall recording usecase criteria */
1809 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1810 if (ret)
1811 goto error_config;
1812 else
1813 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1814
Eric Laurentb23d5282013-05-14 15:27:20 -07001815 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816 if (in->pcm_device_id < 0) {
1817 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1818 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001819 ret = -EINVAL;
1820 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1824 uc_info->id = in->usecase;
1825 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001826 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001827 uc_info->devices = in->device;
1828 uc_info->in_snd_device = SND_DEVICE_NONE;
1829 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001831 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001832
Wei Wangf4837d52017-11-21 14:51:20 -08001833 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001834 audio_extn_perf_lock_acquire();
1835
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837
Eric Laurent0e46adf2016-12-16 12:49:24 -08001838 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001839 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001840 ALOGE("%s: pcm stream not ready", __func__);
1841 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001842 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001843 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001844 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001845 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1846 goto error_open;
1847 }
1848 } else {
1849 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1850 unsigned int pcm_open_retry_count = 0;
1851
1852 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1853 flags |= PCM_MMAP | PCM_NOIRQ;
1854 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1855 } else if (in->realtime) {
1856 flags |= PCM_MMAP | PCM_NOIRQ;
1857 }
1858
1859 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1860 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1861
1862 while (1) {
1863 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1864 flags, &in->config);
1865 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1866 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1867 if (in->pcm != NULL) {
1868 pcm_close(in->pcm);
1869 in->pcm = NULL;
1870 }
1871 if (pcm_open_retry_count-- == 0) {
1872 ret = -EIO;
1873 goto error_open;
1874 }
1875 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1876 continue;
1877 }
1878 break;
1879 }
1880
1881 ALOGV("%s: pcm_prepare", __func__);
1882 ret = pcm_prepare(in->pcm);
1883 if (ret < 0) {
1884 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001885 pcm_close(in->pcm);
1886 in->pcm = NULL;
1887 goto error_open;
1888 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001889 if (in->realtime) {
1890 ret = pcm_start(in->pcm);
1891 if (ret < 0) {
1892 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1893 pcm_close(in->pcm);
1894 in->pcm = NULL;
1895 goto error_open;
1896 }
1897 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001898 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001899 register_in_stream(in);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08001900 check_and_enable_effect(adev);
justinwengc6347db2019-02-21 18:49:00 +08001901 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
1902 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Wei Wangf4837d52017-11-21 14:51:20 -08001903 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001904 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001905 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001906
Eric Laurent0e46adf2016-12-16 12:49:24 -08001907 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001908
1909error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001910 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001911 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001912 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001913
1914error_config:
Eric Laurent2bafff12016-03-17 12:17:23 -07001915 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917}
1918
Eric Laurenta1478072015-09-21 17:21:52 -07001919void lock_input_stream(struct stream_in *in)
1920{
1921 pthread_mutex_lock(&in->pre_lock);
1922 pthread_mutex_lock(&in->lock);
1923 pthread_mutex_unlock(&in->pre_lock);
1924}
1925
1926void lock_output_stream(struct stream_out *out)
1927{
1928 pthread_mutex_lock(&out->pre_lock);
1929 pthread_mutex_lock(&out->lock);
1930 pthread_mutex_unlock(&out->pre_lock);
1931}
1932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001933/* must be called with out->lock locked */
1934static int send_offload_cmd_l(struct stream_out* out, int command)
1935{
1936 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1937
1938 ALOGVV("%s %d", __func__, command);
1939
1940 cmd->cmd = command;
1941 list_add_tail(&out->offload_cmd_list, &cmd->node);
1942 pthread_cond_signal(&out->offload_cond);
1943 return 0;
1944}
1945
1946/* must be called iwth out->lock locked */
1947static void stop_compressed_output_l(struct stream_out *out)
1948{
1949 out->offload_state = OFFLOAD_STATE_IDLE;
1950 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001951 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 if (out->compr != NULL) {
1953 compress_stop(out->compr);
1954 while (out->offload_thread_blocked) {
1955 pthread_cond_wait(&out->cond, &out->lock);
1956 }
1957 }
1958}
1959
1960static void *offload_thread_loop(void *context)
1961{
1962 struct stream_out *out = (struct stream_out *) context;
1963 struct listnode *item;
1964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1966 set_sched_policy(0, SP_FOREGROUND);
1967 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1968
1969 ALOGV("%s", __func__);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001970
Eric Laurenta1478072015-09-21 17:21:52 -07001971 lock_output_stream(out);
juyuchenb0f5bfd2018-12-12 17:58:09 +08001972 out->offload_state = OFFLOAD_STATE_IDLE;
1973 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001974 for (;;) {
1975 struct offload_cmd *cmd = NULL;
1976 stream_callback_event_t event;
1977 bool send_callback = false;
1978
1979 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1980 __func__, list_empty(&out->offload_cmd_list),
1981 out->offload_state);
1982 if (list_empty(&out->offload_cmd_list)) {
1983 ALOGV("%s SLEEPING", __func__);
1984 pthread_cond_wait(&out->offload_cond, &out->lock);
1985 ALOGV("%s RUNNING", __func__);
1986 continue;
1987 }
1988
1989 item = list_head(&out->offload_cmd_list);
1990 cmd = node_to_item(item, struct offload_cmd, node);
1991 list_remove(item);
1992
1993 ALOGVV("%s STATE %d CMD %d out->compr %p",
1994 __func__, out->offload_state, cmd->cmd, out->compr);
1995
1996 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1997 free(cmd);
1998 break;
1999 }
2000
2001 if (out->compr == NULL) {
2002 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07002003 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002004 pthread_cond_signal(&out->cond);
2005 continue;
2006 }
2007 out->offload_thread_blocked = true;
2008 pthread_mutex_unlock(&out->lock);
2009 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002010 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
2012 compress_wait(out->compr, -1);
2013 send_callback = true;
2014 event = STREAM_CBK_EVENT_WRITE_READY;
2015 break;
2016 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002017 compress_next_track(out->compr);
2018 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 send_callback = true;
2020 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002021 /* Resend the metadata for next iteration */
2022 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002023 break;
2024 case OFFLOAD_CMD_DRAIN:
2025 compress_drain(out->compr);
2026 send_callback = true;
2027 event = STREAM_CBK_EVENT_DRAIN_READY;
2028 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002029 case OFFLOAD_CMD_ERROR:
2030 send_callback = true;
2031 event = STREAM_CBK_EVENT_ERROR;
2032 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002033 default:
2034 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2035 break;
2036 }
Eric Laurenta1478072015-09-21 17:21:52 -07002037 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 out->offload_thread_blocked = false;
2039 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07002040 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08002041 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002043 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 free(cmd);
2045 }
2046
2047 pthread_cond_signal(&out->cond);
2048 while (!list_empty(&out->offload_cmd_list)) {
2049 item = list_head(&out->offload_cmd_list);
2050 list_remove(item);
2051 free(node_to_item(item, struct offload_cmd, node));
2052 }
2053 pthread_mutex_unlock(&out->lock);
2054
2055 return NULL;
2056}
2057
2058static int create_offload_callback_thread(struct stream_out *out)
2059{
2060 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2061 list_init(&out->offload_cmd_list);
2062 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2063 offload_thread_loop, out);
2064 return 0;
2065}
2066
2067static int destroy_offload_callback_thread(struct stream_out *out)
2068{
Eric Laurenta1478072015-09-21 17:21:52 -07002069 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070 stop_compressed_output_l(out);
2071 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2072
2073 pthread_mutex_unlock(&out->lock);
2074 pthread_join(out->offload_thread, (void **) NULL);
2075 pthread_cond_destroy(&out->offload_cond);
2076
2077 return 0;
2078}
2079
Eric Laurent07eeafd2013-10-06 12:52:49 -07002080static bool allow_hdmi_channel_config(struct audio_device *adev)
2081{
2082 struct listnode *node;
2083 struct audio_usecase *usecase;
2084 bool ret = true;
2085
2086 list_for_each(node, &adev->usecase_list) {
2087 usecase = node_to_item(node, struct audio_usecase, list);
2088 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2089 /*
2090 * If voice call is already existing, do not proceed further to avoid
2091 * disabling/enabling both RX and TX devices, CSD calls, etc.
2092 * Once the voice call done, the HDMI channels can be configured to
2093 * max channels of remaining use cases.
2094 */
2095 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08002096 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07002097 __func__);
2098 ret = false;
2099 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002100 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
2101 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07002102 "no change in HDMI channels", __func__);
2103 ret = false;
2104 break;
2105 }
2106 }
2107 }
2108 return ret;
2109}
2110
2111static int check_and_set_hdmi_channels(struct audio_device *adev,
2112 unsigned int channels)
2113{
2114 struct listnode *node;
2115 struct audio_usecase *usecase;
2116
2117 /* Check if change in HDMI channel config is allowed */
2118 if (!allow_hdmi_channel_config(adev))
2119 return 0;
2120
2121 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08002122 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002123 return 0;
2124 }
2125
2126 platform_set_hdmi_channels(adev->platform, channels);
2127 adev->cur_hdmi_channels = channels;
2128
2129 /*
2130 * Deroute all the playback streams routed to HDMI so that
2131 * the back end is deactivated. Note that backend will not
2132 * be deactivated if any one stream is connected to it.
2133 */
2134 list_for_each(node, &adev->usecase_list) {
2135 usecase = node_to_item(node, struct audio_usecase, list);
2136 if (usecase->type == PCM_PLAYBACK &&
2137 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002138 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002139 }
2140 }
2141
2142 /*
2143 * Enable all the streams disabled above. Now the HDMI backend
2144 * will be activated with new channel configuration
2145 */
2146 list_for_each(node, &adev->usecase_list) {
2147 usecase = node_to_item(node, struct audio_usecase, list);
2148 if (usecase->type == PCM_PLAYBACK &&
2149 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002150 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002151 }
2152 }
2153
2154 return 0;
2155}
2156
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002157static int check_and_set_usb_service_interval(struct audio_device *adev,
2158 struct audio_usecase *uc_info,
2159 bool min)
2160{
2161 struct listnode *node;
2162 struct audio_usecase *usecase;
2163 bool switch_usecases = false;
2164 bool reconfig = false;
2165
2166 if ((uc_info->id != USECASE_AUDIO_PLAYBACK_MMAP) &&
2167 (uc_info->id != USECASE_AUDIO_PLAYBACK_ULL))
2168 return -1;
2169
2170 /* set if the valid usecase do not already exist */
2171 list_for_each(node, &adev->usecase_list) {
2172 usecase = node_to_item(node, struct audio_usecase, list);
2173 if (usecase->type == PCM_PLAYBACK &&
2174 (audio_is_usb_out_device(usecase->devices & AUDIO_DEVICE_OUT_ALL_USB))) {
2175 switch (usecase->id) {
2176 case USECASE_AUDIO_PLAYBACK_MMAP:
2177 case USECASE_AUDIO_PLAYBACK_ULL:
2178 // cannot reconfig while mmap/ull is present.
2179 return -1;
2180 default:
2181 switch_usecases = true;
2182 break;
2183 }
2184 }
2185 if (switch_usecases)
2186 break;
2187 }
2188 /*
2189 * client can try to set service interval in start_output_stream
2190 * to min or to 0 (i.e reset) in stop_output_stream .
2191 */
2192 unsigned long service_interval =
2193 audio_extn_usb_find_service_interval(min, true /*playback*/);
2194 int ret = platform_set_usb_service_interval(adev->platform,
2195 true /*playback*/,
2196 service_interval,
2197 &reconfig);
2198 /* no change or not supported or no active usecases */
2199 if (ret || !reconfig || !switch_usecases)
2200 return -1;
2201 return 0;
2202#undef VALID_USECASE
2203}
2204
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205static int stop_output_stream(struct stream_out *out)
2206{
2207 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 struct audio_usecase *uc_info;
2209 struct audio_device *adev = out->dev;
HW Lee88512e92018-06-12 15:26:09 +08002210 bool has_voip_usecase =
2211 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212
Eric Laurent994a6932013-07-17 11:51:42 -07002213 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002214 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 uc_info = get_usecase_from_list(adev, out->usecase);
2216 if (uc_info == NULL) {
2217 ALOGE("%s: Could not find the usecase (%d) in the list",
2218 __func__, out->usecase);
2219 return -EINVAL;
2220 }
2221
Haynes Mathew George41f86652014-06-17 14:22:15 -07002222 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2223 if (adev->visualizer_stop_output != NULL)
2224 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
2225 if (adev->offload_effects_stop_output != NULL)
2226 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002227 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2228 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2229 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07002230 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002231
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002232 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2233 voice_set_device_mute_flag(adev, false);
2234
Eric Laurent150dbfe2013-02-27 14:31:02 -08002235 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002236 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002237
2238 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07002239 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002241 list_remove(&uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
Eric Laurent0499d4f2014-08-25 22:39:29 -05002243 audio_extn_extspk_update(adev->extspk);
2244
Eric Laurent07eeafd2013-10-06 12:52:49 -07002245 /* Must be called after removing the usecase from list */
2246 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2247 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
HW Lee88512e92018-06-12 15:26:09 +08002248 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002249 ret = check_and_set_usb_service_interval(adev, uc_info, false /*min*/);
2250 if (ret == 0) {
2251 /* default service interval was successfully updated,
2252 reopen USB backend with new service interval */
2253 check_and_route_playback_usecases(adev, uc_info, uc_info->out_snd_device);
2254 }
2255 ret = 0;
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07002256 }
juyuchend194b432018-11-16 14:15:16 +08002257 /* 1) media + voip output routing to handset must route media back to
2258 speaker when voip stops.
2259 2) trigger voip input to reroute when voip output changes to
2260 hearing aid. */
HW Lee88512e92018-06-12 15:26:09 +08002261 if (has_voip_usecase ||
2262 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
2263 struct listnode *node;
2264 struct audio_usecase *usecase;
2265 list_for_each(node, &adev->usecase_list) {
2266 usecase = node_to_item(node, struct audio_usecase, list);
juyuchend194b432018-11-16 14:15:16 +08002267 if ((usecase->type == PCM_CAPTURE &&
2268 usecase->id != USECASE_AUDIO_RECORD_VOIP)
2269 || usecase == uc_info)
HW Lee88512e92018-06-12 15:26:09 +08002270 continue;
2271
2272 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
2273 __func__, usecase->id, use_case_table[usecase->id],
2274 out->usecase, use_case_table[out->usecase]);
2275 select_devices(adev, usecase->id);
2276 }
2277 }
2278
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002279 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07002280 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 return ret;
2282}
2283
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002284struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
2285 unsigned int flags, unsigned int pcm_open_retry_count,
2286 struct pcm_config *config)
2287{
2288 struct pcm* pcm = NULL;
2289
2290 while (1) {
2291 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
2292 if (pcm == NULL || !pcm_is_ready(pcm)) {
2293 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
2294 if (pcm != NULL) {
2295 pcm_close(pcm);
2296 pcm = NULL;
2297 }
2298 if (pcm_open_retry_count-- == 0)
2299 return NULL;
2300
2301 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2302 continue;
2303 }
2304 break;
2305 }
2306
2307 if (pcm_is_ready(pcm)) {
2308 int ret = pcm_prepare(pcm);
2309 if (ret < 0) {
2310 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2311 pcm_close(pcm);
2312 pcm = NULL;
2313 }
2314 }
2315
2316 return pcm;
2317}
2318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319int start_output_stream(struct stream_out *out)
2320{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322 struct audio_usecase *uc_info;
2323 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002324 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002326 ALOGV("%s: enter: usecase(%d: %s) %s devices(%#x)",
2327 __func__, out->usecase, use_case_table[out->usecase],
2328 out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS ? "(with haptics)" : "",
2329 out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002330
2331 if (out->card_status == CARD_STATUS_OFFLINE ||
2332 adev->card_status == CARD_STATUS_OFFLINE) {
2333 ALOGW("out->card_status or adev->card_status offline, try again");
2334 ret = -EAGAIN;
2335 goto error_config;
2336 }
2337
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002338 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2339 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002340 if (out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002341 a2dp_combo = true;
2342 } else {
2343 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2344 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2345 ret = -EAGAIN;
2346 goto error_config;
2347 }
2348 }
2349 }
2350 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002351 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352 if (out->pcm_device_id < 0) {
2353 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2354 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002355 ret = -EINVAL;
2356 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 }
2358
2359 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
2360 uc_info->id = out->usecase;
2361 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002362 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002363 uc_info->devices = out->devices;
2364 uc_info->in_snd_device = SND_DEVICE_NONE;
2365 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366
Eric Laurent07eeafd2013-10-06 12:52:49 -07002367 /* This must be called before adding this usecase to the list */
2368 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2369 check_and_set_hdmi_channels(adev, out->config.channels);
Haynes Mathew George65f6b432018-02-27 17:44:55 -08002370 else if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
2371 check_and_set_usb_service_interval(adev, uc_info, true /*min*/);
2372 /* USB backend is not reopened immediately.
2373 This is eventually done as part of select_devices */
2374 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002375
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002376 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377
Wei Wangf4837d52017-11-21 14:51:20 -08002378 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002379 audio_extn_perf_lock_acquire();
2380
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002381 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2382 (!audio_extn_a2dp_is_ready())) {
2383 if (!a2dp_combo) {
2384 check_a2dp_restore_l(adev, out, false);
2385 } else {
2386 audio_devices_t dev = out->devices;
juyuchen9baad392018-06-05 19:02:10 +08002387 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2388 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2389 else
2390 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002391 select_devices(adev, out->usecase);
2392 out->devices = dev;
2393 }
2394 } else {
2395 select_devices(adev, out->usecase);
2396 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002397
Eric Laurent0499d4f2014-08-25 22:39:29 -05002398 audio_extn_extspk_update(adev->extspk);
2399
Arun Mirpuri0cc2f312018-05-29 17:26:07 -07002400 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
2401 voice_set_device_mute_flag(adev, true);
2402
Andy Hung31aca912014-03-20 17:14:59 -07002403 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002404 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002405 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2406 out->pcm = NULL;
2407 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
2408 COMPRESS_IN, &out->compr_config);
2409 if (out->compr && !is_compress_ready(out->compr)) {
2410 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2411 compress_close(out->compr);
2412 out->compr = NULL;
2413 ret = -EIO;
2414 goto error_open;
2415 }
2416 if (out->offload_callback)
2417 compress_nonblock(out->compr, out->non_blocking);
2418
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07002419 if (adev->visualizer_start_output != NULL) {
2420 int capture_device_id =
2421 platform_get_pcm_device_id(USECASE_AUDIO_RECORD_AFE_PROXY,
2422 PCM_CAPTURE);
2423 adev->visualizer_start_output(out->handle, out->pcm_device_id,
2424 adev->snd_card, capture_device_id);
2425 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002426 if (adev->offload_effects_start_output != NULL)
2427 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2428 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002429 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002430 ALOGE("%s: pcm stream not ready", __func__);
2431 goto error_open;
2432 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002433 ret = pcm_start(out->pcm);
2434 if (ret < 0) {
2435 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2436 goto error_open;
2437 }
2438 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002439 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002440 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002441
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002442 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2443 flags |= PCM_MMAP | PCM_NOIRQ;
2444 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002445 } else if (out->realtime) {
2446 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002447 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002448
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002449 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
2450 flags, pcm_open_retry_count,
2451 &(out->config));
2452 if (out->pcm == NULL) {
2453 ret = -EIO;
2454 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002455 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002456
2457 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2458 if (adev->haptic_pcm != NULL) {
2459 pcm_close(adev->haptic_pcm);
2460 adev->haptic_pcm = NULL;
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002461 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002462 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
2463 adev->haptic_pcm_device_id,
2464 flags, pcm_open_retry_count,
2465 &(adev->haptics_config));
2466 // failure to open haptics pcm shouldnt stop audio,
2467 // so do not close audio pcm in case of error
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002468 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002469
Eric Laurent0e46adf2016-12-16 12:49:24 -08002470 if (out->realtime) {
2471 ret = pcm_start(out->pcm);
2472 if (ret < 0) {
2473 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2474 pcm_close(out->pcm);
2475 out->pcm = NULL;
2476 goto error_open;
2477 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002478 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002479 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002480
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002481 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002482 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002483 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002484 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002485
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002486 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2487 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2488 audio_low_latency_hint_start();
2489 }
2490
vivek mehtae59cfb22017-06-16 15:57:11 -07002491 // consider a scenario where on pause lower layers are tear down.
2492 // so on resume, swap mixer control need to be sent only when
2493 // backend is active, hence rather than sending from enable device
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002494 // sending it from start of stream
vivek mehtae59cfb22017-06-16 15:57:11 -07002495
2496 platform_set_swap_channels(adev, true);
2497
Eric Laurent994a6932013-07-17 11:51:42 -07002498 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002499 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500error_open:
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002501 if (adev->haptic_pcm) {
2502 pcm_close(adev->haptic_pcm);
2503 adev->haptic_pcm = NULL;
2504 }
Wei Wangf4837d52017-11-21 14:51:20 -08002505 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002506 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002508error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002509 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510}
2511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512static int check_input_parameters(uint32_t sample_rate,
2513 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002514 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002516 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2517 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002518 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2519 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002520 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2521 return -EINVAL;
2522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523
Eric Laurent74b55762017-07-09 17:04:53 -07002524 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2525 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002526 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002527 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002528 return -EINVAL;
2529 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530
2531 switch (sample_rate) {
2532 case 8000:
2533 case 11025:
2534 case 12000:
2535 case 16000:
2536 case 22050:
2537 case 24000:
2538 case 32000:
2539 case 44100:
2540 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002541 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 break;
2543 default:
vivek mehtadae44712015-07-27 14:13:18 -07002544 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 return -EINVAL;
2546 }
2547
2548 return 0;
2549}
2550
Kevin Rocarda325aa22018-04-03 09:15:52 -07002551/** Add a value in a list if not already present.
2552 * @return true if value was successfully inserted or already present,
2553 * false if the list is full and does not contain the value.
2554 */
2555static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
2556 for (size_t i = 0; i < list_length; i++) {
2557 if (list[i] == value) return true; // value is already present
2558 if (list[i] == 0) { // no values in this slot
2559 list[i] = value;
2560 return true; // value inserted
2561 }
2562 }
2563 return false; // could not insert value
2564}
2565
2566/** Add channel_mask in supported_channel_masks if not already present.
2567 * @return true if channel_mask was successfully inserted or already present,
2568 * false if supported_channel_masks is full and does not contain channel_mask.
2569 */
2570static void register_channel_mask(audio_channel_mask_t channel_mask,
2571 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
2572 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
2573 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
2574}
2575
2576/** Add format in supported_formats if not already present.
2577 * @return true if format was successfully inserted or already present,
2578 * false if supported_formats is full and does not contain format.
2579 */
2580static void register_format(audio_format_t format,
2581 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
2582 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
2583 "%s: stream can not declare supporting its format %x", __func__, format);
2584}
2585/** Add sample_rate in supported_sample_rates if not already present.
2586 * @return true if sample_rate was successfully inserted or already present,
2587 * false if supported_sample_rates is full and does not contain sample_rate.
2588 */
2589static void register_sample_rate(uint32_t sample_rate,
2590 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
2591 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
2592 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
2593}
2594
vivek mehtaa68fea62017-06-08 19:04:02 -07002595static size_t get_stream_buffer_size(size_t duration_ms,
2596 uint32_t sample_rate,
2597 audio_format_t format,
2598 int channel_count,
2599 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 size_t size = 0;
2602
vivek mehtaa68fea62017-06-08 19:04:02 -07002603 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002604 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002605 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002606
2607 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608
Glenn Kasten4f993392014-05-14 07:30:48 -07002609 /* make sure the size is multiple of 32 bytes
2610 * At 48 kHz mono 16-bit PCM:
2611 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2612 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2613 */
2614 size += 0x1f;
2615 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002616
2617 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618}
2619
2620static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2621{
2622 struct stream_out *out = (struct stream_out *)stream;
2623
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002624 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625}
2626
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002627static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628{
2629 return -ENOSYS;
2630}
2631
2632static size_t out_get_buffer_size(const struct audio_stream *stream)
2633{
2634 struct stream_out *out = (struct stream_out *)stream;
2635
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002636 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2637 return out->compr_config.fragment_size;
2638 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002639 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002640 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641}
2642
2643static uint32_t out_get_channels(const struct audio_stream *stream)
2644{
2645 struct stream_out *out = (struct stream_out *)stream;
2646
2647 return out->channel_mask;
2648}
2649
2650static audio_format_t out_get_format(const struct audio_stream *stream)
2651{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 struct stream_out *out = (struct stream_out *)stream;
2653
2654 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655}
2656
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002657static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658{
2659 return -ENOSYS;
2660}
2661
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002662/* must be called with out->lock locked */
2663static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664{
2665 struct stream_out *out = (struct stream_out *)stream;
2666 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002667 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002670 if (adev->adm_deregister_stream)
2671 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002672 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2675 if (out->pcm) {
2676 pcm_close(out->pcm);
2677 out->pcm = NULL;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08002678
2679 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
2680 if (adev->haptic_pcm) {
2681 pcm_close(adev->haptic_pcm);
2682 adev->haptic_pcm = NULL;
2683 }
2684
2685 if (adev->haptic_buffer != NULL) {
2686 free(adev->haptic_buffer);
2687 adev->haptic_buffer = NULL;
2688 adev->haptic_buffer_size = 0;
2689 }
2690 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002691 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002692 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002693 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002694 out->playback_started = false;
2695 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002696 } else {
2697 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002698 out->gapless_mdata.encoder_delay = 0;
2699 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 if (out->compr != NULL) {
2701 compress_close(out->compr);
2702 out->compr = NULL;
2703 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002704 }
Phil Burkbc991042017-02-24 08:06:44 -08002705 if (do_stop) {
2706 stop_output_stream(out);
2707 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002708 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002710 return 0;
2711}
2712
2713static int out_standby(struct audio_stream *stream)
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716
2717 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2718 out->usecase, use_case_table[out->usecase]);
2719
2720 lock_output_stream(out);
2721 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002723 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724 return 0;
2725}
2726
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002727static int out_on_error(struct audio_stream *stream)
2728{
2729 struct stream_out *out = (struct stream_out *)stream;
2730 struct audio_device *adev = out->dev;
2731 bool do_standby = false;
2732
2733 lock_output_stream(out);
2734 if (!out->standby) {
2735 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2736 stop_compressed_output_l(out);
2737 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2738 } else
2739 do_standby = true;
2740 }
2741 pthread_mutex_unlock(&out->lock);
2742
2743 if (do_standby)
2744 return out_standby(&out->stream.common);
2745
2746 return 0;
2747}
2748
Andy Hung7401c7c2016-09-21 12:41:21 -07002749static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750{
Andy Hung7401c7c2016-09-21 12:41:21 -07002751 struct stream_out *out = (struct stream_out *)stream;
2752
2753 // We try to get the lock for consistency,
2754 // but it isn't necessary for these variables.
2755 // If we're not in standby, we may be blocked on a write.
2756 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2757 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2758 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2759
Andy Hung572633e2019-02-19 11:58:24 -08002760 char buffer[256]; // for statistics formatting
2761 simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer));
2762 dprintf(fd, " Fifo frame underruns: %s\n", buffer);
2763
Andy Hung241e36f2019-02-19 12:00:38 -08002764 if (out->start_latency_ms.n > 0) {
2765 simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer));
2766 dprintf(fd, " Start latency ms: %s\n", buffer);
2767 }
2768
Andy Hung7401c7c2016-09-21 12:41:21 -07002769 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002770 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002771 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002772
2773 // dump error info
2774 (void)error_log_dump(
2775 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002777 return 0;
2778}
2779
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002780static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2781{
2782 int ret = 0;
2783 char value[32];
2784 struct compr_gapless_mdata tmp_mdata;
2785
2786 if (!out || !parms) {
2787 return -EINVAL;
2788 }
2789
2790 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2791 if (ret >= 0) {
2792 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2793 } else {
2794 return -EINVAL;
2795 }
2796
2797 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2798 if (ret >= 0) {
2799 tmp_mdata.encoder_padding = atoi(value);
2800 } else {
2801 return -EINVAL;
2802 }
2803
2804 out->gapless_mdata = tmp_mdata;
2805 out->send_new_metadata = 1;
2806 ALOGV("%s new encoder delay %u and padding %u", __func__,
2807 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2808
2809 return 0;
2810}
2811
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002812static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2813{
2814 return out == adev->primary_output || out == adev->voice_tx_output;
2815}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002816
Kevin Rocard1e02c882017-08-09 15:26:07 -07002817static int get_alive_usb_card(struct str_parms* parms) {
2818 int card;
2819 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2820 !audio_extn_usb_alive(card)) {
2821 return card;
2822 }
2823 return -ENODEV;
2824}
2825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2827{
2828 struct stream_out *out = (struct stream_out *)stream;
2829 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002830 struct audio_usecase *usecase;
2831 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 struct str_parms *parms;
2833 char value[32];
2834 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002835 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002836 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002837 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838
Eric Laurent2e140aa2016-06-30 17:14:46 -07002839 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002840 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841 parms = str_parms_create_str(kvpairs);
2842 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2843 if (ret >= 0) {
2844 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002845
Eric Laurenta1478072015-09-21 17:21:52 -07002846 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002847
2848 // The usb driver needs to be closed after usb device disconnection
2849 // otherwise audio is no longer played on the new usb devices.
2850 // By forcing the stream in standby, the usb stack refcount drops to 0
2851 // and the driver is closed.
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002852 if (val == AUDIO_DEVICE_NONE &&
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002853 audio_is_usb_out_device(out->devices)) {
Aniket Kumar Lataad4dfc32018-07-10 16:04:59 -07002854 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2855 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2856 out_standby_l(&out->stream.common);
2857 }
2858 val = AUDIO_DEVICE_OUT_SPEAKER;
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002859 }
2860
Eric Laurent150dbfe2013-02-27 14:31:02 -08002861 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002863 /*
2864 * When HDMI cable is unplugged the music playback is paused and
2865 * the policy manager sends routing=0. But the audioflinger
2866 * continues to write data until standby time (3sec).
2867 * As the HDMI core is turned off, the write gets blocked.
2868 * Avoid this by routing audio to speaker until standby.
2869 */
2870 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2871 val == AUDIO_DEVICE_NONE) {
2872 val = AUDIO_DEVICE_OUT_SPEAKER;
2873 }
2874
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002875 /*
2876 * When A2DP is disconnected the
2877 * music playback is paused and the policy manager sends routing=0
2878 * But the audioflingercontinues to write data until standby time
2879 * (3sec). As BT is turned off, the write gets blocked.
2880 * Avoid this by routing audio to speaker until standby.
2881 */
2882 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2883 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07002884 !audio_extn_a2dp_is_ready() &&
2885 !adev->bt_sco_on) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002886 val = AUDIO_DEVICE_OUT_SPEAKER;
2887 }
2888
2889 /* To avoid a2dp to sco overlapping / BT device improper state
2890 * check with BT lib about a2dp streaming support before routing
2891 */
2892 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2893 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002894 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002895 //combo usecase just by pass a2dp
2896 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2897 bypass_a2dp = true;
2898 } else {
2899 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2900 /* update device to a2dp and don't route as BT returned error
2901 * However it is still possible a2dp routing called because
2902 * of current active device disconnection (like wired headset)
2903 */
2904 out->devices = val;
2905 pthread_mutex_unlock(&out->lock);
2906 pthread_mutex_unlock(&adev->lock);
2907 status = -ENOSYS;
2908 goto routing_fail;
2909 }
2910 }
2911 }
2912
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002913 audio_devices_t new_dev = val;
2914
2915 // Workaround: If routing to an non existing usb device, fail gracefully
2916 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002917 int card;
2918 if (audio_is_usb_out_device(new_dev) &&
2919 (card = get_alive_usb_card(parms)) >= 0) {
2920
2921 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002922 pthread_mutex_unlock(&adev->lock);
2923 pthread_mutex_unlock(&out->lock);
2924 status = -ENOSYS;
2925 goto routing_fail;
2926 }
2927
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002928 /*
2929 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002930 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002931 * the select_devices(). But how do we undo this?
2932 *
2933 * For example, music playback is active on headset (deep-buffer usecase)
2934 * and if we go to ringtones and select a ringtone, low-latency usecase
2935 * will be started on headset+speaker. As we can't enable headset+speaker
2936 * and headset devices at the same time, select_devices() switches the music
2937 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2938 * So when the ringtone playback is completed, how do we undo the same?
2939 *
2940 * We are relying on the out_set_parameters() call on deep-buffer output,
2941 * once the ringtone playback is ended.
2942 * NOTE: We should not check if the current devices are same as new devices.
2943 * Because select_devices() must be called to switch back the music
2944 * playback to headset.
2945 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002946 if (new_dev != AUDIO_DEVICE_NONE) {
2947 bool same_dev = out->devices == new_dev;
2948 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002949
Eric Laurenta7657192014-10-09 21:09:33 -07002950 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002951 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002952 if (adev->mode == AUDIO_MODE_IN_CALL) {
2953 adev->current_call_output = out;
2954 ret = voice_start_call(adev);
2955 }
2956 } else {
2957 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002958 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002959 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002960 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002961
2962 if (!out->standby) {
2963 if (!same_dev) {
2964 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002965 // inform adm before actual routing to prevent glitches.
2966 if (adev->adm_on_routing_change) {
2967 adev->adm_on_routing_change(adev->adm_data,
2968 out->handle);
2969 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002970 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002971 if (!bypass_a2dp) {
2972 select_devices(adev, out->usecase);
2973 } else {
juyuchen9baad392018-06-05 19:02:10 +08002974 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2975 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2976 else
2977 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002978 select_devices(adev, out->usecase);
2979 out->devices = new_dev;
2980 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002981 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002982
2983 // on device switch force swap, lower functions will make sure
2984 // to check if swap is allowed or not.
2985
2986 if (!same_dev)
2987 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002988
2989 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2990 out->a2dp_compress_mute &&
2991 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2992 pthread_mutex_lock(&out->compr_mute_lock);
2993 out->a2dp_compress_mute = false;
2994 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2995 pthread_mutex_unlock(&out->compr_mute_lock);
2996 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002997 }
2998
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002999 }
3000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003002 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003003
3004 /*handles device and call state changes*/
3005 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003007 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003008
3009 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3010 parse_compress_metadata(out, parms);
3011 }
3012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003014 ALOGV("%s: exit: code(%d)", __func__, status);
3015 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016}
3017
Haynes Mathew George569b7482017-05-08 14:44:27 -07003018static bool stream_get_parameter_channels(struct str_parms *query,
3019 struct str_parms *reply,
3020 audio_channel_mask_t *supported_channel_masks) {
3021 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003022 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003024 size_t i, j;
3025
3026 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3027 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 value[0] = '\0';
3029 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003030 while (supported_channel_masks[i] != 0) {
3031 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3032 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 if (!first) {
3034 strcat(value, "|");
3035 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003036 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 first = false;
3038 break;
3039 }
3040 }
3041 i++;
3042 }
3043 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003044 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003045 return ret >= 0;
3046}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003047
Haynes Mathew George569b7482017-05-08 14:44:27 -07003048static bool stream_get_parameter_formats(struct str_parms *query,
3049 struct str_parms *reply,
3050 audio_format_t *supported_formats) {
3051 int ret = -1;
3052 char value[256];
3053 int i;
3054
3055 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3056 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003057 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003058 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003059 case AUDIO_FORMAT_PCM_16_BIT:
3060 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3061 break;
3062 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3063 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3064 break;
3065 case AUDIO_FORMAT_PCM_32_BIT:
3066 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3067 break;
3068 default:
3069 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003070 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003071 break;
3072 }
3073 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003074 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003075 return ret >= 0;
3076}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003077
Haynes Mathew George569b7482017-05-08 14:44:27 -07003078static bool stream_get_parameter_rates(struct str_parms *query,
3079 struct str_parms *reply,
3080 uint32_t *supported_sample_rates) {
3081
3082 int i;
3083 char value[256];
3084 int ret = -1;
3085 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3086 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003087 value[0] = '\0';
3088 i=0;
3089 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003090 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003091 int avail = sizeof(value) - cursor;
3092 ret = snprintf(value + cursor, avail, "%s%d",
3093 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003094 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003095 if (ret < 0 || ret >= avail) {
3096 // if cursor is at the last element of the array
3097 // overwrite with \0 is duplicate work as
3098 // snprintf already put a \0 in place.
3099 // else
3100 // we had space to write the '|' at value[cursor]
3101 // (which will be overwritten) or no space to fill
3102 // the first element (=> cursor == 0)
3103 value[cursor] = '\0';
3104 break;
3105 }
3106 cursor += ret;
3107 ++i;
3108 }
3109 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3110 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003111 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003112 return ret >= 0;
3113}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003114
Haynes Mathew George569b7482017-05-08 14:44:27 -07003115static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3116{
3117 struct stream_out *out = (struct stream_out *)stream;
3118 struct str_parms *query = str_parms_create_str(keys);
3119 char *str;
3120 struct str_parms *reply = str_parms_create();
3121 bool replied = false;
3122 ALOGV("%s: enter: keys - %s", __func__, keys);
3123
3124 replied |= stream_get_parameter_channels(query, reply,
3125 &out->supported_channel_masks[0]);
3126 replied |= stream_get_parameter_formats(query, reply,
3127 &out->supported_formats[0]);
3128 replied |= stream_get_parameter_rates(query, reply,
3129 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003130 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131 str = str_parms_to_str(reply);
3132 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003133 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134 }
3135 str_parms_destroy(query);
3136 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003137 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003138 return str;
3139}
3140
3141static uint32_t out_get_latency(const struct audio_stream_out *stream)
3142{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003143 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003145 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3148 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003149 else if ((out->realtime) ||
3150 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003151 // since the buffer won't be filled up faster than realtime,
3152 // return a smaller number
3153 period_ms = (out->af_period_multiplier * out->config.period_size *
3154 1000) / (out->config.rate);
3155 hw_delay = platform_render_latency(out->usecase)/1000;
3156 return period_ms + hw_delay;
3157 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003159 latency = (out->config.period_count * out->config.period_size * 1000) /
3160 (out->config.rate);
3161
3162 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3163 latency += audio_extn_a2dp_get_encoder_latency();
3164
3165 return latency;
3166}
3167
3168static int set_compr_volume(struct audio_stream_out *stream, float left,
3169 float right)
3170{
3171 struct stream_out *out = (struct stream_out *)stream;
3172 int volume[2];
3173 char mixer_ctl_name[128];
3174 struct audio_device *adev = out->dev;
3175 struct mixer_ctl *ctl;
3176 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3177 PCM_PLAYBACK);
3178
3179 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3180 "Compress Playback %d Volume", pcm_device_id);
3181 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3182 if (!ctl) {
3183 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3184 __func__, mixer_ctl_name);
3185 return -EINVAL;
3186 }
3187 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3188 __func__, mixer_ctl_name, left, right);
3189 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3190 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3191 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3192
3193 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194}
3195
3196static int out_set_volume(struct audio_stream_out *stream, float left,
3197 float right)
3198{
Eric Laurenta9024de2013-04-04 09:19:12 -07003199 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003200 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003202 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003203 /* only take left channel into account: the API is for stereo anyway */
3204 out->muted = (left == 0.0f);
3205 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003206 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003207 pthread_mutex_lock(&out->compr_mute_lock);
3208 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3209 if (!out->a2dp_compress_mute)
3210 ret = set_compr_volume(stream, left, right);
3211 out->volume_l = left;
3212 out->volume_r = right;
3213 pthread_mutex_unlock(&out->compr_mute_lock);
3214 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003215 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003216 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3217 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3218 if (!out->standby) {
3219 // if in standby, cached volume will be sent after stream is opened
3220 audio_extn_utils_send_app_type_gain(out->dev,
3221 out->app_type_cfg.app_type,
3222 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003223 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003224 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003225 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227 return -ENOSYS;
3228}
3229
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003230// note: this call is safe only if the stream_cb is
3231// removed first in close_output_stream (as is done now).
3232static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3233{
3234 if (!stream || !parms)
3235 return;
3236
3237 struct stream_out *out = (struct stream_out *)stream;
3238 struct audio_device *adev = out->dev;
3239
3240 card_status_t status;
3241 int card;
3242 if (parse_snd_card_status(parms, &card, &status) < 0)
3243 return;
3244
3245 pthread_mutex_lock(&adev->lock);
3246 bool valid_cb = (card == adev->snd_card);
3247 pthread_mutex_unlock(&adev->lock);
3248
3249 if (!valid_cb)
3250 return;
3251
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003252 lock_output_stream(out);
3253 if (out->card_status != status)
3254 out->card_status = status;
3255 pthread_mutex_unlock(&out->lock);
3256
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003257 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3258 use_case_table[out->usecase],
3259 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3260
3261 if (status == CARD_STATUS_OFFLINE)
3262 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003263
3264 return;
3265}
3266
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003267#ifdef NO_AUDIO_OUT
3268static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003269 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003270{
3271 struct stream_out *out = (struct stream_out *)stream;
3272
3273 /* No Output device supported other than BT for playback.
3274 * Sleep for the amount of buffer duration
3275 */
Eric Laurenta1478072015-09-21 17:21:52 -07003276 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003277 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3278 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003279 out_get_sample_rate(&out->stream.common));
3280 pthread_mutex_unlock(&out->lock);
3281 return bytes;
3282}
3283#endif
3284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3286 size_t bytes)
3287{
3288 struct stream_out *out = (struct stream_out *)stream;
3289 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003290 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003291 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292
Eric Laurenta1478072015-09-21 17:21:52 -07003293 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003294 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003295 const size_t frame_size = audio_stream_out_frame_size(stream);
3296 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003297
Eric Laurent0e46adf2016-12-16 12:49:24 -08003298 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3299 error_code = ERROR_CODE_WRITE;
3300 goto exit;
3301 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003302
3303 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3304 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003305 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003306 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3307 ret = -EIO;
3308 goto exit;
3309 }
3310 }
3311 }
3312
Andy Hung572633e2019-02-19 11:58:24 -08003313 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003315 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003316 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3317
Eric Laurent150dbfe2013-02-27 14:31:02 -08003318 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003320
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003321 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003323 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003324 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 goto exit;
3326 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003327
vivek mehta40125092017-08-21 18:48:51 -07003328 // after standby always force set last known cal step
3329 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3330 ALOGD("%s: retry previous failed cal level set", __func__);
3331 send_gain_dep_calibration_l();
3332 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003333
Andy Hung241e36f2019-02-19 12:00:38 -08003334 // log startup time in ms.
3335 simple_stats_log(
3336 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003337 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003341 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003342 if (out->send_new_metadata) {
3343 ALOGVV("send new gapless metadata");
3344 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3345 out->send_new_metadata = 0;
3346 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003347 unsigned int avail;
3348 struct timespec tstamp;
3349 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3350 /* Do not limit write size if the available frames count is unknown */
3351 if (ret != 0) {
3352 avail = bytes;
3353 }
3354 if (avail == 0) {
3355 ret = 0;
3356 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003357 // check for compressed format underrun, essentially an empty buffer check
3358 // for a lack of better measurement.
3359 if (!was_in_standby && avail == out->kernel_buffer_size) {
3360 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3361 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3362 }
3363
Eric Laurentb49b3f62016-02-29 17:59:49 -08003364 if (avail > bytes) {
3365 avail = bytes;
3366 }
3367 ret = compress_write(out->compr, buffer, avail);
3368 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3369 __func__, avail, ret);
3370 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003371
Eric Laurent6e895242013-09-05 16:10:57 -07003372 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003373 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3374 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003375 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003376 compress_start(out->compr);
3377 out->playback_started = 1;
3378 out->offload_state = OFFLOAD_STATE_PLAYING;
3379 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003380 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003381 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003382 } else {
3383 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003384 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003386 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 return ret;
3388 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003389 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003391 size_t bytes_to_write = bytes;
3392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003393 if (out->muted)
3394 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003395 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003396 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003397 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3398 int16_t *src = (int16_t *)buffer;
3399 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003400
Eric Laurentad2dde92017-09-20 18:27:31 -07003401 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3402 out->format != AUDIO_FORMAT_PCM_16_BIT,
3403 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003404
Eric Laurentad2dde92017-09-20 18:27:31 -07003405 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3406 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3407 }
3408 bytes_to_write /= 2;
3409 }
Andy Hung572633e2019-02-19 11:58:24 -08003410
3411 // Note: since out_get_presentation_position() is called alternating with out_write()
3412 // by AudioFlinger, we can check underruns using the prior timestamp read.
3413 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3414 if (out->last_fifo_valid) {
3415 // compute drain to see if there is an underrun.
3416 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3417 const int64_t frames_by_time =
3418 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3419 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3420
3421 if (underrun > 0) {
3422 simple_stats_log(&out->fifo_underruns, underrun);
3423
3424 ALOGW("%s: underrun(%lld) "
3425 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3426 __func__,
3427 (long long)out->fifo_underruns.n,
3428 (long long)frames_by_time,
3429 (long long)out->last_fifo_frames_remaining);
3430 }
3431 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3432 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003433
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003434 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003435 request_out_focus(out, ns);
3436
3437 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003438 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003439 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003440 } else {
3441 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3442 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3443 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3444 size_t frame_size = channel_count * bytes_per_sample;
3445 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003446
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003447 bool force_haptic_path =
3448 property_get_bool("vendor.audio.test_haptic", false);
3449
3450 // extract Haptics data from Audio buffer
3451 bool alloc_haptic_buffer = false;
3452 int haptic_channel_count = adev->haptics_config.channels;
3453 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3454 size_t audio_frame_size = frame_size - haptic_frame_size;
3455 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3456
3457 if (adev->haptic_buffer == NULL) {
3458 alloc_haptic_buffer = true;
3459 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3460 free(adev->haptic_buffer);
3461 adev->haptic_buffer_size = 0;
3462 alloc_haptic_buffer = true;
3463 }
3464
3465 if (alloc_haptic_buffer) {
3466 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3467 adev->haptic_buffer_size = total_haptic_buffer_size;
3468 }
3469
3470 size_t src_index = 0, aud_index = 0, hap_index = 0;
3471 uint8_t *audio_buffer = (uint8_t *)buffer;
3472 uint8_t *haptic_buffer = adev->haptic_buffer;
3473
3474 // This is required for testing only. This works for stereo data only.
3475 // One channel is fed to audio stream and other to haptic stream for testing.
3476 if (force_haptic_path) {
3477 audio_frame_size = haptic_frame_size = bytes_per_sample;
3478 }
3479
3480 for (size_t i = 0; i < frame_count; i++) {
3481 for (size_t j = 0; j < audio_frame_size; j++)
3482 audio_buffer[aud_index++] = audio_buffer[src_index++];
3483
3484 for (size_t j = 0; j < haptic_frame_size; j++)
3485 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3486 }
3487
3488 // This is required for testing only.
3489 // Discard haptic channel data.
3490 if (force_haptic_path) {
3491 src_index += haptic_frame_size;
3492 }
3493
3494 // write to audio pipeline
3495 ret = pcm_write(out->pcm,
3496 (void *)audio_buffer,
3497 frame_count * audio_frame_size);
3498
3499 // write to haptics pipeline
3500 if (adev->haptic_pcm)
3501 ret = pcm_write(adev->haptic_pcm,
3502 (void *)adev->haptic_buffer,
3503 frame_count * haptic_frame_size);
3504
3505 } else {
3506 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3507 }
3508 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003509 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003510 } else {
3511 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 }
3514
3515exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003516 // For PCM we always consume the buffer and return #bytes regardless of ret.
3517 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003518 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003519 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003520 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003521
Andy Hung7401c7c2016-09-21 12:41:21 -07003522 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003523 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003524 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3525 ALOGE_IF(out->pcm != NULL,
3526 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003527 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003528 // usleep not guaranteed for values over 1 second but we don't limit here.
3529 }
3530 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 pthread_mutex_unlock(&out->lock);
3533
3534 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003535 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003536 if (sleeptime_us != 0)
3537 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 }
3539 return bytes;
3540}
3541
3542static int out_get_render_position(const struct audio_stream_out *stream,
3543 uint32_t *dsp_frames)
3544{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003545 struct stream_out *out = (struct stream_out *)stream;
3546 *dsp_frames = 0;
3547 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003548 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003549 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003550 unsigned long frames = 0;
3551 // TODO: check return value
3552 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3553 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003554 ALOGVV("%s rendered frames %d sample_rate %d",
3555 __func__, *dsp_frames, out->sample_rate);
3556 }
3557 pthread_mutex_unlock(&out->lock);
3558 return 0;
3559 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003560 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561}
3562
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003563static int out_add_audio_effect(const struct audio_stream *stream __unused,
3564 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565{
3566 return 0;
3567}
3568
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003569static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3570 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571{
3572 return 0;
3573}
3574
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003575static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3576 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003578 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579}
3580
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003581static int out_get_presentation_position(const struct audio_stream_out *stream,
3582 uint64_t *frames, struct timespec *timestamp)
3583{
3584 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003585 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003586 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003587
Eric Laurenta1478072015-09-21 17:21:52 -07003588 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003589
Eric Laurent949a0892013-09-20 09:20:13 -07003590 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3591 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003592 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003593 compress_get_tstamp(out->compr, &dsp_frames,
3594 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003595 // Adjustment accounts for A2DP encoder latency with offload usecases
3596 // Note: Encoder latency is returned in ms.
3597 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3598 unsigned long offset =
3599 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3600 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3601 }
Eric Laurent949a0892013-09-20 09:20:13 -07003602 ALOGVV("%s rendered frames %ld sample_rate %d",
3603 __func__, dsp_frames, out->sample_rate);
3604 *frames = dsp_frames;
3605 ret = 0;
3606 /* this is the best we can do */
3607 clock_gettime(CLOCK_MONOTONIC, timestamp);
3608 }
3609 } else {
3610 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003611 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003612 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003613
3614 // pcm_get_htimestamp() computes the available frames by comparing
3615 // the alsa driver hw_ptr and the appl_ptr levels.
3616 // In underrun, the hw_ptr may keep running and report an excessively
3617 // large number available number.
3618 if (avail > out->kernel_buffer_size) {
3619 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3620 __func__, avail, out->kernel_buffer_size);
3621 avail = out->kernel_buffer_size;
3622 out->last_fifo_frames_remaining = 0;
3623 } else {
3624 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3625 }
3626 out->last_fifo_valid = true;
3627 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3628
3629 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3630
3631 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3632 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3633
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003634 // This adjustment accounts for buffering after app processor.
3635 // It is based on estimated DSP latency per use case, rather than exact.
3636 signed_frames -=
3637 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3638
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003639 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3640 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3641 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3642 signed_frames -=
3643 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3644 }
3645
Eric Laurent949a0892013-09-20 09:20:13 -07003646 // It would be unusual for this value to be negative, but check just in case ...
3647 if (signed_frames >= 0) {
3648 *frames = signed_frames;
3649 ret = 0;
3650 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003651 }
3652 }
3653 }
3654
3655 pthread_mutex_unlock(&out->lock);
3656
3657 return ret;
3658}
3659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003660static int out_set_callback(struct audio_stream_out *stream,
3661 stream_callback_t callback, void *cookie)
3662{
3663 struct stream_out *out = (struct stream_out *)stream;
3664
3665 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003666 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003667 out->offload_callback = callback;
3668 out->offload_cookie = cookie;
3669 pthread_mutex_unlock(&out->lock);
3670 return 0;
3671}
3672
3673static int out_pause(struct audio_stream_out* stream)
3674{
3675 struct stream_out *out = (struct stream_out *)stream;
3676 int status = -ENOSYS;
3677 ALOGV("%s", __func__);
3678 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003679 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003680 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3681 status = compress_pause(out->compr);
3682 out->offload_state = OFFLOAD_STATE_PAUSED;
3683 }
3684 pthread_mutex_unlock(&out->lock);
3685 }
3686 return status;
3687}
3688
3689static int out_resume(struct audio_stream_out* stream)
3690{
3691 struct stream_out *out = (struct stream_out *)stream;
3692 int status = -ENOSYS;
3693 ALOGV("%s", __func__);
3694 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3695 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003696 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003697 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3698 status = compress_resume(out->compr);
3699 out->offload_state = OFFLOAD_STATE_PLAYING;
3700 }
3701 pthread_mutex_unlock(&out->lock);
3702 }
3703 return status;
3704}
3705
3706static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3707{
3708 struct stream_out *out = (struct stream_out *)stream;
3709 int status = -ENOSYS;
3710 ALOGV("%s", __func__);
3711 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003712 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3714 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3715 else
3716 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3717 pthread_mutex_unlock(&out->lock);
3718 }
3719 return status;
3720}
3721
3722static int out_flush(struct audio_stream_out* stream)
3723{
3724 struct stream_out *out = (struct stream_out *)stream;
3725 ALOGV("%s", __func__);
3726 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003727 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 stop_compressed_output_l(out);
3729 pthread_mutex_unlock(&out->lock);
3730 return 0;
3731 }
3732 return -ENOSYS;
3733}
3734
Eric Laurent0e46adf2016-12-16 12:49:24 -08003735static int out_stop(const struct audio_stream_out* stream)
3736{
3737 struct stream_out *out = (struct stream_out *)stream;
3738 struct audio_device *adev = out->dev;
3739 int ret = -ENOSYS;
3740
3741 ALOGV("%s", __func__);
3742 pthread_mutex_lock(&adev->lock);
3743 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3744 out->playback_started && out->pcm != NULL) {
3745 pcm_stop(out->pcm);
3746 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003747 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003748 }
3749 pthread_mutex_unlock(&adev->lock);
3750 return ret;
3751}
3752
3753static int out_start(const struct audio_stream_out* stream)
3754{
3755 struct stream_out *out = (struct stream_out *)stream;
3756 struct audio_device *adev = out->dev;
3757 int ret = -ENOSYS;
3758
3759 ALOGV("%s", __func__);
3760 pthread_mutex_lock(&adev->lock);
3761 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3762 !out->playback_started && out->pcm != NULL) {
3763 ret = start_output_stream(out);
3764 if (ret == 0) {
3765 out->playback_started = true;
3766 }
3767 }
3768 pthread_mutex_unlock(&adev->lock);
3769 return ret;
3770}
3771
Phil Burkbc991042017-02-24 08:06:44 -08003772/*
3773 * Modify config->period_count based on min_size_frames
3774 */
3775static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3776{
3777 int periodCountRequested = (min_size_frames + config->period_size - 1)
3778 / config->period_size;
3779 int periodCount = MMAP_PERIOD_COUNT_MIN;
3780
3781 ALOGV("%s original config.period_size = %d config.period_count = %d",
3782 __func__, config->period_size, config->period_count);
3783
3784 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3785 periodCount *= 2;
3786 }
3787 config->period_count = periodCount;
3788
3789 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3790}
3791
Phil Burk51e6bc42019-03-25 10:23:35 -07003792// Read offset for the positional timestamp from a persistent vendor property.
3793// This is to workaround apparent inaccuracies in the timing information that
3794// is used by the AAudio timing model. The inaccuracies can cause glitches.
3795static int64_t get_mmap_out_time_offset() {
3796 const int32_t kDefaultOffsetMicros = 0;
3797 int32_t mmap_time_offset_micros = property_get_int32(
3798 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3799 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3800 return mmap_time_offset_micros * (int64_t)1000;
3801}
3802
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3804 int32_t min_size_frames,
3805 struct audio_mmap_buffer_info *info)
3806{
3807 struct stream_out *out = (struct stream_out *)stream;
3808 struct audio_device *adev = out->dev;
3809 int ret = 0;
3810 unsigned int offset1;
3811 unsigned int frames1;
3812 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003813 uint32_t mmap_size;
3814 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003815
3816 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003817 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003818 pthread_mutex_lock(&adev->lock);
3819
3820 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003821 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003822 ret = -EINVAL;
3823 goto exit;
3824 }
3825 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003826 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003827 ret = -ENOSYS;
3828 goto exit;
3829 }
3830 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3831 if (out->pcm_device_id < 0) {
3832 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3833 __func__, out->pcm_device_id, out->usecase);
3834 ret = -EINVAL;
3835 goto exit;
3836 }
Phil Burkbc991042017-02-24 08:06:44 -08003837
3838 adjust_mmap_period_count(&out->config, min_size_frames);
3839
Eric Laurent0e46adf2016-12-16 12:49:24 -08003840 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3841 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3842 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3843 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3844 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3845 step = "open";
3846 ret = -ENODEV;
3847 goto exit;
3848 }
3849 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3850 if (ret < 0) {
3851 step = "begin";
3852 goto exit;
3853 }
3854 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003855 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003856 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003857 ret = platform_get_mmap_data_fd(adev->platform,
3858 out->pcm_device_id, 0 /*playback*/,
3859 &info->shared_memory_fd,
3860 &mmap_size);
3861 if (ret < 0) {
3862 // Fall back to non exclusive mode
3863 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3864 } else {
3865 if (mmap_size < buffer_size) {
3866 step = "mmap";
3867 goto exit;
3868 }
3869 // FIXME: indicate exclusive mode support by returning a negative buffer size
3870 info->buffer_size_frames *= -1;
3871 }
3872 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003873
3874 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3875 if (ret < 0) {
3876 step = "commit";
3877 goto exit;
3878 }
Phil Burkbc991042017-02-24 08:06:44 -08003879
Phil Burk51e6bc42019-03-25 10:23:35 -07003880 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
3881
Phil Burkbc991042017-02-24 08:06:44 -08003882 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003883 ret = 0;
3884
3885 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3886 __func__, info->shared_memory_address, info->buffer_size_frames);
3887
3888exit:
3889 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003890 if (out->pcm == NULL) {
3891 ALOGE("%s: %s - %d", __func__, step, ret);
3892 } else {
3893 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003894 pcm_close(out->pcm);
3895 out->pcm = NULL;
3896 }
3897 }
3898 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003899 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003900 return ret;
3901}
3902
3903static int out_get_mmap_position(const struct audio_stream_out *stream,
3904 struct audio_mmap_position *position)
3905{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003906 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003907 struct stream_out *out = (struct stream_out *)stream;
3908 ALOGVV("%s", __func__);
3909 if (position == NULL) {
3910 return -EINVAL;
3911 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003912 lock_output_stream(out);
3913 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3914 out->pcm == NULL) {
3915 ret = -ENOSYS;
3916 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003917 }
3918
3919 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003920 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003921 if (ret < 0) {
3922 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003923 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003924 }
Phil Burk51e6bc42019-03-25 10:23:35 -07003925 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
3926 + out->mmap_time_offset_nanos;
3927
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003928exit:
3929 pthread_mutex_unlock(&out->lock);
3930 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003931}
3932
3933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934/** audio_stream_in implementation **/
3935static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3936{
3937 struct stream_in *in = (struct stream_in *)stream;
3938
3939 return in->config.rate;
3940}
3941
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003942static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943{
3944 return -ENOSYS;
3945}
3946
3947static size_t in_get_buffer_size(const struct audio_stream *stream)
3948{
3949 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003950 return in->config.period_size * in->af_period_multiplier *
3951 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952}
3953
3954static uint32_t in_get_channels(const struct audio_stream *stream)
3955{
3956 struct stream_in *in = (struct stream_in *)stream;
3957
3958 return in->channel_mask;
3959}
3960
vivek mehta4ed66e62016-04-15 23:33:34 -07003961static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962{
vivek mehta4ed66e62016-04-15 23:33:34 -07003963 struct stream_in *in = (struct stream_in *)stream;
3964 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965}
3966
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003967static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968{
3969 return -ENOSYS;
3970}
3971
3972static int in_standby(struct audio_stream *stream)
3973{
3974 struct stream_in *in = (struct stream_in *)stream;
3975 struct audio_device *adev = in->dev;
3976 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003977 bool do_stop = true;
3978
Eric Laurent994a6932013-07-17 11:51:42 -07003979 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003980
3981 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003982
3983 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003984 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003985 audio_extn_sound_trigger_stop_lab(in);
3986 in->standby = true;
3987 }
3988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003990 if (adev->adm_deregister_stream)
3991 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3992
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003993 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003994 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003995 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003996 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003997 in->capture_started = false;
3998 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003999 if (in->pcm) {
4000 pcm_close(in->pcm);
4001 in->pcm = NULL;
4002 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05004003 adev->enable_voicerx = false;
4004 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08004005 if (do_stop) {
4006 status = stop_input_stream(in);
4007 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004008 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 }
4010 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004011 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012 return status;
4013}
4014
Andy Hungd13f0d32017-06-12 13:58:37 -07004015static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016{
Andy Hungd13f0d32017-06-12 13:58:37 -07004017 struct stream_in *in = (struct stream_in *)stream;
4018
4019 // We try to get the lock for consistency,
4020 // but it isn't necessary for these variables.
4021 // If we're not in standby, we may be blocked on a read.
4022 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4023 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4024 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4025 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4026
Andy Hung241e36f2019-02-19 12:00:38 -08004027 char buffer[256]; // for statistics formatting
4028 if (in->start_latency_ms.n > 0) {
4029 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4030 dprintf(fd, " Start latency ms: %s\n", buffer);
4031 }
4032
Andy Hungd13f0d32017-06-12 13:58:37 -07004033 if (locked) {
4034 pthread_mutex_unlock(&in->lock);
4035 }
4036
4037 // dump error info
4038 (void)error_log_dump(
4039 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040 return 0;
4041}
4042
4043static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4044{
4045 struct stream_in *in = (struct stream_in *)stream;
4046 struct audio_device *adev = in->dev;
4047 struct str_parms *parms;
4048 char *str;
4049 char value[32];
4050 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004051 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004052
Eric Laurent994a6932013-07-17 11:51:42 -07004053 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 parms = str_parms_create_str(kvpairs);
4055
4056 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4057
Eric Laurenta1478072015-09-21 17:21:52 -07004058 lock_input_stream(in);
4059
Eric Laurent150dbfe2013-02-27 14:31:02 -08004060 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 if (ret >= 0) {
4062 val = atoi(value);
4063 /* no audio source uses val == 0 */
4064 if ((in->source != val) && (val != 0)) {
4065 in->source = val;
4066 }
4067 }
4068
4069 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004070
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 if (ret >= 0) {
4072 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004073 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004074
4075 // Workaround: If routing to an non existing usb device, fail gracefully
4076 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004077 int card;
4078 if (audio_is_usb_in_device(val) &&
4079 (card = get_alive_usb_card(parms)) >= 0) {
4080
4081 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004082 status = -ENOSYS;
4083 } else {
4084
4085 in->device = val;
4086 /* If recording is in progress, change the tx device to new device */
4087 if (!in->standby) {
4088 ALOGV("update input routing change");
4089 // inform adm before actual routing to prevent glitches.
4090 if (adev->adm_on_routing_change) {
4091 adev->adm_on_routing_change(adev->adm_data,
4092 in->capture_handle);
4093 }
4094 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004095 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004096 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004097 }
4098 }
4099
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004101 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102
4103 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004104 ALOGV("%s: exit: status(%d)", __func__, status);
4105 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106}
4107
Haynes Mathew George569b7482017-05-08 14:44:27 -07004108static char* in_get_parameters(const struct audio_stream *stream,
4109 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004111 struct stream_in *in = (struct stream_in *)stream;
4112 struct str_parms *query = str_parms_create_str(keys);
4113 char *str;
4114 struct str_parms *reply = str_parms_create();
4115 bool replied = false;
4116
4117 ALOGV("%s: enter: keys - %s", __func__, keys);
4118 replied |= stream_get_parameter_channels(query, reply,
4119 &in->supported_channel_masks[0]);
4120 replied |= stream_get_parameter_formats(query, reply,
4121 &in->supported_formats[0]);
4122 replied |= stream_get_parameter_rates(query, reply,
4123 &in->supported_sample_rates[0]);
4124 if (replied) {
4125 str = str_parms_to_str(reply);
4126 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004127 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004128 }
4129 str_parms_destroy(query);
4130 str_parms_destroy(reply);
4131 ALOGV("%s: exit: returns - %s", __func__, str);
4132 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133}
4134
Eric Laurent51f3c662018-04-10 18:21:34 -07004135static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136{
Eric Laurent51f3c662018-04-10 18:21:34 -07004137 struct stream_in *in = (struct stream_in *)stream;
4138 char mixer_ctl_name[128];
4139 struct mixer_ctl *ctl;
4140 int ctl_value;
4141
4142 ALOGV("%s: gain %f", __func__, gain);
4143
4144 if (stream == NULL)
4145 return -EINVAL;
4146
4147 /* in_set_gain() only used to silence MMAP capture for now */
4148 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4149 return -ENOSYS;
4150
4151 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4152
4153 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4154 if (!ctl) {
4155 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4156 __func__, mixer_ctl_name);
4157 return -ENOSYS;
4158 }
4159
4160 if (gain < RECORD_GAIN_MIN)
4161 gain = RECORD_GAIN_MIN;
4162 else if (gain > RECORD_GAIN_MAX)
4163 gain = RECORD_GAIN_MAX;
4164 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4165
4166 mixer_ctl_set_value(ctl, 0, ctl_value);
4167 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168}
4169
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004170static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4171{
4172 if (!stream || !parms)
4173 return;
4174
4175 struct stream_in *in = (struct stream_in *)stream;
4176 struct audio_device *adev = in->dev;
4177
4178 card_status_t status;
4179 int card;
4180 if (parse_snd_card_status(parms, &card, &status) < 0)
4181 return;
4182
4183 pthread_mutex_lock(&adev->lock);
4184 bool valid_cb = (card == adev->snd_card);
4185 pthread_mutex_unlock(&adev->lock);
4186
4187 if (!valid_cb)
4188 return;
4189
4190 lock_input_stream(in);
4191 if (in->card_status != status)
4192 in->card_status = status;
4193 pthread_mutex_unlock(&in->lock);
4194
4195 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4196 use_case_table[in->usecase],
4197 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4198
4199 // a better solution would be to report error back to AF and let
4200 // it put the stream to standby
4201 if (status == CARD_STATUS_OFFLINE)
4202 in_standby(&in->stream.common);
4203
4204 return;
4205}
4206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4208 size_t bytes)
4209{
4210 struct stream_in *in = (struct stream_in *)stream;
4211 struct audio_device *adev = in->dev;
4212 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004213 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004214 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
Eric Laurenta1478072015-09-21 17:21:52 -07004216 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004217 const size_t frame_size = audio_stream_in_frame_size(stream);
4218 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004219
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004220 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004221 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004222 /* Read from sound trigger HAL */
4223 audio_extn_sound_trigger_read(in, buffer, bytes);
4224 pthread_mutex_unlock(&in->lock);
4225 return bytes;
4226 }
4227
Eric Laurent0e46adf2016-12-16 12:49:24 -08004228 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4229 ret = -ENOSYS;
4230 goto exit;
4231 }
4232
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004234 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4235
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004236 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004238 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240 goto exit;
4241 }
4242 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004243
4244 // log startup time in ms.
4245 simple_stats_log(
4246 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248
Andy Hungd13f0d32017-06-12 13:58:37 -07004249 // errors that occur here are read errors.
4250 error_code = ERROR_CODE_READ;
4251
Haynes Mathew George03c40102016-01-29 17:57:48 -08004252 //what's the duration requested by the client?
4253 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4254 in->config.rate;
4255 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004256
Haynes Mathew George03c40102016-01-29 17:57:48 -08004257 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004259 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004260 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004261 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004262 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004263 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004264 if (ret < 0) {
4265 ALOGE("Failed to read w/err %s", strerror(errno));
4266 ret = -errno;
4267 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004268 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4269 if (bytes % 4 == 0) {
4270 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4271 int_buf_stream = buffer;
4272 for (size_t itt=0; itt < bytes/4 ; itt++) {
4273 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004274 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004275 } else {
4276 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4277 ret = -EINVAL;
4278 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004279 }
4280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 }
4282
Haynes Mathew George03c40102016-01-29 17:57:48 -08004283 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004284
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004285 /*
4286 * Instead of writing zeroes here, we could trust the hardware
4287 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004288 * 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 -08004289 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004290 if (ret == 0 && adev->mic_muted &&
4291 !voice_is_in_call_rec_stream(in) &&
4292 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004293 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004294 in->frames_muted += frames;
4295 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004296
4297exit:
4298 pthread_mutex_unlock(&in->lock);
4299
4300 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004301 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302 in_standby(&in->stream.common);
4303 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004304 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004305 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004306 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004307 }
4308 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004309 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 }
4311 return bytes;
4312}
4313
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004314static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004315{
4316 return 0;
4317}
4318
Andy Hung6ebe5962016-01-15 17:46:57 -08004319static int in_get_capture_position(const struct audio_stream_in *stream,
4320 int64_t *frames, int64_t *time)
4321{
4322 if (stream == NULL || frames == NULL || time == NULL) {
4323 return -EINVAL;
4324 }
4325 struct stream_in *in = (struct stream_in *)stream;
4326 int ret = -ENOSYS;
4327
4328 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004329 // note: ST sessions do not close the alsa pcm driver synchronously
4330 // on standby. Therefore, we may return an error even though the
4331 // pcm stream is still opened.
4332 if (in->standby) {
4333 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4334 "%s stream in standby but pcm not NULL for non ST session", __func__);
4335 goto exit;
4336 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004337 if (in->pcm) {
4338 struct timespec timestamp;
4339 unsigned int avail;
4340 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4341 *frames = in->frames_read + avail;
4342 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4343 ret = 0;
4344 }
4345 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004346exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004347 pthread_mutex_unlock(&in->lock);
4348 return ret;
4349}
4350
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004351static int add_remove_audio_effect(const struct audio_stream *stream,
4352 effect_handle_t effect,
4353 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004355 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004356 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004357 int status = 0;
4358 effect_descriptor_t desc;
4359
4360 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004361 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4362
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004363 if (status != 0)
4364 return status;
4365
Eric Laurenta1478072015-09-21 17:21:52 -07004366 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004367 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004368 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004369 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004370 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004371 in->enable_aec != enable &&
4372 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4373 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004374 if (!enable)
4375 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004376 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4377 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4378 adev->enable_voicerx = enable;
4379 struct audio_usecase *usecase;
4380 struct listnode *node;
4381 list_for_each(node, &adev->usecase_list) {
4382 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004383 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004384 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004385 }
4386 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004387 if (!in->standby
4388 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004389 select_devices(in->dev, in->usecase);
4390 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004391 if (in->enable_ns != enable &&
4392 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4393 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004394 if (!in->standby) {
4395 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4396 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4397 select_devices(in->dev, in->usecase);
4398 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004399 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004400 pthread_mutex_unlock(&in->dev->lock);
4401 pthread_mutex_unlock(&in->lock);
4402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 return 0;
4404}
4405
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004406static int in_add_audio_effect(const struct audio_stream *stream,
4407 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408{
Eric Laurent994a6932013-07-17 11:51:42 -07004409 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004410 return add_remove_audio_effect(stream, effect, true);
4411}
4412
4413static int in_remove_audio_effect(const struct audio_stream *stream,
4414 effect_handle_t effect)
4415{
Eric Laurent994a6932013-07-17 11:51:42 -07004416 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004417 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418}
4419
Eric Laurent0e46adf2016-12-16 12:49:24 -08004420static int in_stop(const struct audio_stream_in* stream)
4421{
4422 struct stream_in *in = (struct stream_in *)stream;
4423 struct audio_device *adev = in->dev;
4424
4425 int ret = -ENOSYS;
4426 ALOGV("%s", __func__);
4427 pthread_mutex_lock(&adev->lock);
4428 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4429 in->capture_started && in->pcm != NULL) {
4430 pcm_stop(in->pcm);
4431 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004432 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004433 }
4434 pthread_mutex_unlock(&adev->lock);
4435 return ret;
4436}
4437
4438static int in_start(const struct audio_stream_in* stream)
4439{
4440 struct stream_in *in = (struct stream_in *)stream;
4441 struct audio_device *adev = in->dev;
4442 int ret = -ENOSYS;
4443
4444 ALOGV("%s in %p", __func__, in);
4445 pthread_mutex_lock(&adev->lock);
4446 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4447 !in->capture_started && in->pcm != NULL) {
4448 if (!in->capture_started) {
4449 ret = start_input_stream(in);
4450 if (ret == 0) {
4451 in->capture_started = true;
4452 }
4453 }
4454 }
4455 pthread_mutex_unlock(&adev->lock);
4456 return ret;
4457}
4458
Phil Burk8a6a1652019-03-25 10:15:59 -07004459// Read offset for the positional timestamp from a persistent vendor property.
4460// This is to workaround apparent inaccuracies in the timing information that
4461// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004462static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004463 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004464 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004465 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004466 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4467 return mmap_time_offset_micros * (int64_t)1000;
4468}
4469
Eric Laurent0e46adf2016-12-16 12:49:24 -08004470static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4471 int32_t min_size_frames,
4472 struct audio_mmap_buffer_info *info)
4473{
4474 struct stream_in *in = (struct stream_in *)stream;
4475 struct audio_device *adev = in->dev;
4476 int ret = 0;
4477 unsigned int offset1;
4478 unsigned int frames1;
4479 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004480 uint32_t mmap_size;
4481 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004482
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004483 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004484 pthread_mutex_lock(&adev->lock);
4485 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004486
Eric Laurent0e46adf2016-12-16 12:49:24 -08004487 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004488 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004489 ret = -EINVAL;
4490 goto exit;
4491 }
4492 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004493 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004494 ALOGV("%s in %p", __func__, in);
4495 ret = -ENOSYS;
4496 goto exit;
4497 }
4498 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4499 if (in->pcm_device_id < 0) {
4500 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4501 __func__, in->pcm_device_id, in->usecase);
4502 ret = -EINVAL;
4503 goto exit;
4504 }
Phil Burkbc991042017-02-24 08:06:44 -08004505
4506 adjust_mmap_period_count(&in->config, min_size_frames);
4507
Eric Laurent0e46adf2016-12-16 12:49:24 -08004508 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4509 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4510 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4511 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4512 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4513 step = "open";
4514 ret = -ENODEV;
4515 goto exit;
4516 }
4517
4518 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4519 if (ret < 0) {
4520 step = "begin";
4521 goto exit;
4522 }
4523 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004524 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004525 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004526 ret = platform_get_mmap_data_fd(adev->platform,
4527 in->pcm_device_id, 1 /*capture*/,
4528 &info->shared_memory_fd,
4529 &mmap_size);
4530 if (ret < 0) {
4531 // Fall back to non exclusive mode
4532 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4533 } else {
4534 if (mmap_size < buffer_size) {
4535 step = "mmap";
4536 goto exit;
4537 }
4538 // FIXME: indicate exclusive mode support by returning a negative buffer size
4539 info->buffer_size_frames *= -1;
4540 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004541
Haynes Mathew George96483a22017-03-28 14:52:47 -07004542 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004543
4544 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4545 if (ret < 0) {
4546 step = "commit";
4547 goto exit;
4548 }
4549
Phil Burkc4714fc2019-02-16 22:28:11 -08004550 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4551
Phil Burkbc991042017-02-24 08:06:44 -08004552 in->standby = false;
4553 ret = 0;
4554
Eric Laurent0e46adf2016-12-16 12:49:24 -08004555 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4556 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004557
4558exit:
4559 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004560 if (in->pcm == NULL) {
4561 ALOGE("%s: %s - %d", __func__, step, ret);
4562 } else {
4563 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004564 pcm_close(in->pcm);
4565 in->pcm = NULL;
4566 }
4567 }
4568 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004569 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004570 return ret;
4571}
4572
4573static int in_get_mmap_position(const struct audio_stream_in *stream,
4574 struct audio_mmap_position *position)
4575{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004576 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004577 struct stream_in *in = (struct stream_in *)stream;
4578 ALOGVV("%s", __func__);
4579 if (position == NULL) {
4580 return -EINVAL;
4581 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004582 lock_input_stream(in);
4583 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4584 in->pcm == NULL) {
4585 ret = -ENOSYS;
4586 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004587 }
4588 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004589 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004590 if (ret < 0) {
4591 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004592 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004593 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004594 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4595 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004596
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004597exit:
4598 pthread_mutex_unlock(&in->lock);
4599 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004600}
4601
jiabin8962a4d2018-03-19 18:21:24 -07004602static int in_get_active_microphones(const struct audio_stream_in *stream,
4603 struct audio_microphone_characteristic_t *mic_array,
4604 size_t *mic_count) {
4605 struct stream_in *in = (struct stream_in *)stream;
4606 struct audio_device *adev = in->dev;
4607 ALOGVV("%s", __func__);
4608
4609 lock_input_stream(in);
4610 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004611 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004612 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004613 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004614 pthread_mutex_unlock(&adev->lock);
4615 pthread_mutex_unlock(&in->lock);
4616
4617 return ret;
4618}
4619
4620static int adev_get_microphones(const struct audio_hw_device *dev,
4621 struct audio_microphone_characteristic_t *mic_array,
4622 size_t *mic_count) {
4623 struct audio_device *adev = (struct audio_device *)dev;
4624 ALOGVV("%s", __func__);
4625
4626 pthread_mutex_lock(&adev->lock);
4627 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4628 pthread_mutex_unlock(&adev->lock);
4629
4630 return ret;
4631}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004632
Paul McLean57530d52018-12-17 08:24:21 -07004633static int in_set_microphone_direction(const struct audio_stream_in *stream,
4634 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004635 struct stream_in *in = (struct stream_in *)stream;
4636
4637 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4638
4639 in->direction = dir;
4640
4641 if (in->standby)
4642 return 0;
4643
4644 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004645}
4646
4647static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004648 struct stream_in *in = (struct stream_in *)stream;
4649
4650 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4651
4652 if (zoom > 1.0 || zoom < -1.0)
4653 return -EINVAL;
4654
4655 in->zoom = zoom;
4656
4657 if (in->standby)
4658 return 0;
4659
4660 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004661}
4662
juyuchenba338cd2019-01-21 11:57:17 +08004663static void in_update_sink_metadata(struct audio_stream_in *stream,
4664 const struct sink_metadata *sink_metadata) {
4665
4666 if (stream == NULL
4667 || sink_metadata == NULL
4668 || sink_metadata->tracks == NULL) {
4669 return;
4670 }
4671
4672 int error = 0;
4673 struct stream_in *in = (struct stream_in *)stream;
4674 struct audio_device *adev = in->dev;
4675 audio_devices_t device = AUDIO_DEVICE_NONE;
4676
4677 if (sink_metadata->track_count != 0)
4678 device = sink_metadata->tracks->dest_device;
4679
4680 lock_input_stream(in);
4681 pthread_mutex_lock(&adev->lock);
4682 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4683
4684 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4685 && device != AUDIO_DEVICE_NONE
4686 && adev->voice_tx_output != NULL) {
4687 /* Use the rx device from afe-proxy record to route voice call because
4688 there is no routing if tx device is on primary hal and rx device
4689 is on other hal during voice call. */
4690 adev->voice_tx_output->devices = device;
4691
4692 if (!voice_is_call_state_active(adev)) {
4693 if (adev->mode == AUDIO_MODE_IN_CALL) {
4694 adev->current_call_output = adev->voice_tx_output;
4695 error = voice_start_call(adev);
4696 if (error != 0)
4697 ALOGE("%s: start voice call failed %d", __func__, error);
4698 }
4699 } else {
4700 adev->current_call_output = adev->voice_tx_output;
4701 voice_update_devices_for_all_voice_usecases(adev);
4702 }
4703 }
4704
4705 pthread_mutex_unlock(&adev->lock);
4706 pthread_mutex_unlock(&in->lock);
4707}
4708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709static int adev_open_output_stream(struct audio_hw_device *dev,
4710 audio_io_handle_t handle,
4711 audio_devices_t devices,
4712 audio_output_flags_t flags,
4713 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004714 struct audio_stream_out **stream_out,
4715 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716{
4717 struct audio_device *adev = (struct audio_device *)dev;
4718 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004719 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004720 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4721 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4722 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004723 bool force_haptic_path =
4724 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725
Andy Hungd9653bd2017-08-01 19:31:39 -07004726 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4727 return -ENOSYS;
4728 }
4729
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004730 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4731 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733 *stream_out = NULL;
4734 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4735
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004736 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 if (devices == AUDIO_DEVICE_NONE)
4739 devices = AUDIO_DEVICE_OUT_SPEAKER;
4740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 out->flags = flags;
4742 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004743 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004744 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004745 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004746
4747 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004748 if ((is_hdmi || is_usb_dev) &&
4749 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4750 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4751 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004752 audio_format_t req_format = config->format;
4753 audio_channel_mask_t req_channel_mask = config->channel_mask;
4754 uint32_t req_sample_rate = config->sample_rate;
4755
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004756 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004757 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004758 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004759 if (config->sample_rate == 0)
4760 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004761 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004762 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4763 if (config->format == AUDIO_FORMAT_DEFAULT)
4764 config->format = AUDIO_FORMAT_PCM_16_BIT;
4765 } else if (is_usb_dev) {
4766 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4767 &config->format,
4768 &out->supported_formats[0],
4769 MAX_SUPPORTED_FORMATS,
4770 &config->channel_mask,
4771 &out->supported_channel_masks[0],
4772 MAX_SUPPORTED_CHANNEL_MASKS,
4773 &config->sample_rate,
4774 &out->supported_sample_rates[0],
4775 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004776 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004777 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004778 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004779 if (ret != 0) {
4780 // For MMAP NO IRQ, allow conversions in ADSP
4781 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4782 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004783
Eric Laurentab805ee2018-03-30 12:20:38 -07004784 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4785 config->sample_rate = req_sample_rate;
4786 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4787 config->channel_mask = req_channel_mask;
4788 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4789 config->format = req_format;
4790 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004791
Haynes Mathew George569b7482017-05-08 14:44:27 -07004792 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004793 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004794 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004795 if (is_hdmi) {
4796 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4797 out->config = pcm_config_hdmi_multi;
4798 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4799 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4800 out->config = pcm_config_mmap_playback;
4801 out->stream.start = out_start;
4802 out->stream.stop = out_stop;
4803 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4804 out->stream.get_mmap_position = out_get_mmap_position;
4805 } else {
4806 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4807 out->config = pcm_config_hifi;
4808 }
4809
4810 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004811 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004812 if (is_hdmi) {
4813 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4814 audio_bytes_per_sample(out->format));
4815 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004816 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004817 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004818 pthread_mutex_lock(&adev->lock);
4819 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4820 pthread_mutex_unlock(&adev->lock);
4821
4822 // reject offload during card offline to allow
4823 // fallback to s/w paths
4824 if (offline) {
4825 ret = -ENODEV;
4826 goto error_open;
4827 }
4828
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004829 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4830 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4831 ALOGE("%s: Unsupported Offload information", __func__);
4832 ret = -EINVAL;
4833 goto error_open;
4834 }
4835 if (!is_supported_format(config->offload_info.format)) {
4836 ALOGE("%s: Unsupported audio format", __func__);
4837 ret = -EINVAL;
4838 goto error_open;
4839 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004840 out->sample_rate = config->offload_info.sample_rate;
4841 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4842 out->channel_mask = config->offload_info.channel_mask;
4843 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4844 out->channel_mask = config->channel_mask;
4845 else
4846 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4847
4848 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004849
4850 out->compr_config.codec = (struct snd_codec *)
4851 calloc(1, sizeof(struct snd_codec));
4852
4853 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004854
4855 out->stream.set_callback = out_set_callback;
4856 out->stream.pause = out_pause;
4857 out->stream.resume = out_resume;
4858 out->stream.drain = out_drain;
4859 out->stream.flush = out_flush;
4860
4861 out->compr_config.codec->id =
4862 get_snd_codec_id(config->offload_info.format);
4863 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4864 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004865 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004866 out->compr_config.codec->bit_rate =
4867 config->offload_info.bit_rate;
4868 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004869 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004870 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4871
4872 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4873 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004874
4875 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004876 create_offload_callback_thread(out);
4877 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4878 __func__, config->offload_info.version,
4879 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004880 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4881 switch (config->sample_rate) {
4882 case 0:
4883 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4884 break;
4885 case 8000:
4886 case 16000:
4887 case 48000:
4888 out->sample_rate = config->sample_rate;
4889 break;
4890 default:
4891 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4892 config->sample_rate);
4893 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4894 ret = -EINVAL;
4895 goto error_open;
4896 }
4897 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4898 switch (config->channel_mask) {
4899 case AUDIO_CHANNEL_NONE:
4900 case AUDIO_CHANNEL_OUT_STEREO:
4901 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4902 break;
4903 default:
4904 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4905 config->channel_mask);
4906 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4907 ret = -EINVAL;
4908 goto error_open;
4909 }
4910 switch (config->format) {
4911 case AUDIO_FORMAT_DEFAULT:
4912 case AUDIO_FORMAT_PCM_16_BIT:
4913 out->format = AUDIO_FORMAT_PCM_16_BIT;
4914 break;
4915 default:
4916 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4917 config->format);
4918 config->format = AUDIO_FORMAT_PCM_16_BIT;
4919 ret = -EINVAL;
4920 goto error_open;
4921 }
4922
4923 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004924 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004925 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004926 case 0:
4927 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4928 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004929 case 8000:
4930 case 16000:
4931 case 48000:
4932 out->sample_rate = config->sample_rate;
4933 break;
4934 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004935 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4936 config->sample_rate);
4937 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4938 ret = -EINVAL;
4939 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004940 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004941 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4942 switch (config->channel_mask) {
4943 case AUDIO_CHANNEL_NONE:
4944 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4945 break;
4946 case AUDIO_CHANNEL_OUT_STEREO:
4947 out->channel_mask = config->channel_mask;
4948 break;
4949 default:
4950 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4951 config->channel_mask);
4952 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4953 ret = -EINVAL;
4954 break;
4955 }
4956 switch (config->format) {
4957 case AUDIO_FORMAT_DEFAULT:
4958 out->format = AUDIO_FORMAT_PCM_16_BIT;
4959 break;
4960 case AUDIO_FORMAT_PCM_16_BIT:
4961 out->format = config->format;
4962 break;
4963 default:
4964 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4965 config->format);
4966 config->format = AUDIO_FORMAT_PCM_16_BIT;
4967 ret = -EINVAL;
4968 break;
4969 }
4970 if (ret != 0)
4971 goto error_open;
4972
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004973 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4974 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004975 out->config.rate = out->sample_rate;
4976 out->config.channels =
4977 audio_channel_count_from_out_mask(out->channel_mask);
4978 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004979 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004980 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4981 switch (config->sample_rate) {
4982 case 0:
4983 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4984 break;
4985 case 8000:
4986 case 16000:
4987 case 32000:
4988 case 48000:
4989 out->sample_rate = config->sample_rate;
4990 break;
4991 default:
4992 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4993 config->sample_rate);
4994 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4995 ret = -EINVAL;
4996 break;
4997 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004998 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004999 switch (config->channel_mask) {
5000 case AUDIO_CHANNEL_NONE:
5001 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5002 break;
5003 case AUDIO_CHANNEL_OUT_STEREO:
5004 out->channel_mask = config->channel_mask;
5005 break;
5006 default:
5007 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
5008 config->channel_mask);
5009 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5010 ret = -EINVAL;
5011 break;
5012 }
5013 switch (config->format) {
5014 case AUDIO_FORMAT_DEFAULT:
5015 out->format = AUDIO_FORMAT_PCM_16_BIT;
5016 break;
5017 case AUDIO_FORMAT_PCM_16_BIT:
5018 out->format = config->format;
5019 break;
5020 default:
5021 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5022 config->format);
5023 config->format = AUDIO_FORMAT_PCM_16_BIT;
5024 ret = -EINVAL;
5025 break;
5026 }
5027 if (ret != 0)
5028 goto error_open;
5029
vivek mehtaa68fea62017-06-08 19:04:02 -07005030 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005031 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5032 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005033 out->config.rate = out->sample_rate;
5034 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005035 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005036 out->sample_rate,
5037 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005038 out->config.channels,
5039 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005040 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005041 out->config.period_size = buffer_size / frame_size;
5042 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5043 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005044 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005045 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005046 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5047 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005048 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005049 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5050 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005051 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005052 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005053 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005054 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005055 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005056 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5057 out->config = pcm_config_mmap_playback;
5058 out->stream.start = out_start;
5059 out->stream.stop = out_stop;
5060 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5061 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005062 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005063 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5064 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5065 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5066 if (adev->haptic_pcm_device_id < 0) {
5067 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5068 __func__, adev->haptic_pcm_device_id, out->usecase);
5069 ret = -ENOSYS;
5070 goto error_open;
5071 }
5072 out->config = pcm_config_haptics_audio;
5073 if (force_haptic_path)
5074 adev->haptics_config = pcm_config_haptics_audio;
5075 else
5076 adev->haptics_config = pcm_config_haptics;
5077 } else {
5078 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5079 out->config = pcm_config_low_latency;
5080 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005081 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005082
5083 if (config->sample_rate == 0) {
5084 out->sample_rate = out->config.rate;
5085 } else {
5086 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005087 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005088
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005089 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5090 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5091 } else {
5092 out->channel_mask = config->channel_mask;
5093 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005094
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005095 if (config->format == AUDIO_FORMAT_DEFAULT)
5096 out->format = audio_format_from_pcm_format(out->config.format);
5097 else if (!audio_is_linear_pcm(config->format)) {
5098 config->format = AUDIO_FORMAT_PCM_16_BIT;
5099 ret = -EINVAL;
5100 goto error_open;
5101 } else {
5102 out->format = config->format;
5103 }
5104
5105 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005106
5107 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5108 out->config.channels =
5109 audio_channel_count_from_out_mask(out->channel_mask &
5110 ~AUDIO_CHANNEL_HAPTIC_ALL);
5111
5112 if (force_haptic_path) {
5113 out->config.channels = 1;
5114 adev->haptics_config.channels = 1;
5115 } else {
5116 adev->haptics_config.channels =
5117 audio_channel_count_from_out_mask(out->channel_mask &
5118 AUDIO_CHANNEL_HAPTIC_ALL);
5119 }
5120 } else {
5121 out->config.channels =
5122 audio_channel_count_from_out_mask(out->channel_mask);
5123 }
5124
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005125 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5126 out->config.format = pcm_format_from_audio_format(out->format);
5127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005128 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005129
5130 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5131 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005132 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005133 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5134 __func__, config->sample_rate, config->format, config->channel_mask);
5135 config->sample_rate = out->sample_rate;
5136 config->format = out->format;
5137 config->channel_mask = out->channel_mask;
5138 ret = -EINVAL;
5139 goto error_open;
5140 }
5141
Andy Hung6fcba9c2014-03-18 11:53:32 -07005142 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5143 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005144
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005145 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005146 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005147 adev->primary_output = out;
5148 else {
5149 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005150 ret = -EEXIST;
5151 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005152 }
5153 }
5154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005155 /* Check if this usecase is already existing */
5156 pthread_mutex_lock(&adev->lock);
5157 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5158 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005159 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005160 ret = -EEXIST;
5161 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005162 }
5163 pthread_mutex_unlock(&adev->lock);
5164
5165 out->stream.common.get_sample_rate = out_get_sample_rate;
5166 out->stream.common.set_sample_rate = out_set_sample_rate;
5167 out->stream.common.get_buffer_size = out_get_buffer_size;
5168 out->stream.common.get_channels = out_get_channels;
5169 out->stream.common.get_format = out_get_format;
5170 out->stream.common.set_format = out_set_format;
5171 out->stream.common.standby = out_standby;
5172 out->stream.common.dump = out_dump;
5173 out->stream.common.set_parameters = out_set_parameters;
5174 out->stream.common.get_parameters = out_get_parameters;
5175 out->stream.common.add_audio_effect = out_add_audio_effect;
5176 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5177 out->stream.get_latency = out_get_latency;
5178 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005179#ifdef NO_AUDIO_OUT
5180 out->stream.write = out_write_for_no_output;
5181#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005182 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005183#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005184 out->stream.get_render_position = out_get_render_position;
5185 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005186 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005187
Eric Laurent0e46adf2016-12-16 12:49:24 -08005188 if (out->realtime)
5189 out->af_period_multiplier = af_period_multiplier;
5190 else
5191 out->af_period_multiplier = 1;
5192
Andy Hung572633e2019-02-19 11:58:24 -08005193 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005195 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005196 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005197 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005198
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005199 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005200 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005201 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005203 config->format = out->stream.common.get_format(&out->stream.common);
5204 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5205 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5206
Kevin Rocarda325aa22018-04-03 09:15:52 -07005207 register_format(out->format, out->supported_formats);
5208 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5209 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5210
Andy Hunga452b0a2017-03-15 14:51:15 -07005211 out->error_log = error_log_create(
5212 ERROR_LOG_ENTRIES,
5213 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5214
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005215 /*
5216 By locking output stream before registering, we allow the callback
5217 to update stream's state only after stream's initial state is set to
5218 adev state.
5219 */
5220 lock_output_stream(out);
5221 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5222 pthread_mutex_lock(&adev->lock);
5223 out->card_status = adev->card_status;
5224 pthread_mutex_unlock(&adev->lock);
5225 pthread_mutex_unlock(&out->lock);
5226
vivek mehta4a824772017-06-08 19:05:49 -07005227 stream_app_type_cfg_init(&out->app_type_cfg);
5228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005229 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005230
Eric Laurent994a6932013-07-17 11:51:42 -07005231 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005232 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005233
5234error_open:
5235 free(out);
5236 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005237 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005238 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005239}
5240
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005241static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005242 struct audio_stream_out *stream)
5243{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005244 struct stream_out *out = (struct stream_out *)stream;
5245 struct audio_device *adev = out->dev;
5246
Eric Laurent994a6932013-07-17 11:51:42 -07005247 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005248
5249 // must deregister from sndmonitor first to prevent races
5250 // between the callback and close_stream
5251 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005253 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5254 destroy_offload_callback_thread(out);
5255
5256 if (out->compr_config.codec != NULL)
5257 free(out->compr_config.codec);
5258 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005259
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005260 out->a2dp_compress_mute = false;
5261
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005262 if (adev->voice_tx_output == out)
5263 adev->voice_tx_output = NULL;
5264
Andy Hunga452b0a2017-03-15 14:51:15 -07005265 error_log_destroy(out->error_log);
5266 out->error_log = NULL;
5267
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005268 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005269 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005270 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005271 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005272 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005273}
5274
5275static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5276{
5277 struct audio_device *adev = (struct audio_device *)dev;
5278 struct str_parms *parms;
5279 char *str;
5280 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005281 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005282 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005283 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005284 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005285
Joe Onorato188b6222016-03-01 11:02:27 -08005286 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005287
5288 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005289
5290 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005291 status = voice_set_parameters(adev, parms);
5292 if (status != 0) {
5293 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005294 }
5295
5296 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5297 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005298 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5300 adev->bluetooth_nrec = true;
5301 else
5302 adev->bluetooth_nrec = false;
5303 }
5304
5305 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5306 if (ret >= 0) {
5307 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5308 adev->screen_off = false;
5309 else
5310 adev->screen_off = true;
5311 }
5312
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005313 ret = str_parms_get_int(parms, "rotation", &val);
5314 if (ret >= 0) {
5315 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005316 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005317 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005318 // FIXME: note that the code below assumes that the speakers are in the correct placement
5319 // relative to the user when the device is rotated 90deg from its default rotation. This
5320 // assumption is device-specific, not platform-specific like this code.
5321 case 270:
5322 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005323 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005324 break;
5325 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005326 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005327 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5328 break;
5329 case 90:
5330 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005331 break;
5332 default:
5333 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005334 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005335 }
Eric Laurent03f09432014-03-25 18:09:11 -07005336 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005337 // check and set swap
5338 // - check if orientation changed and speaker active
5339 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005340 adev->camera_orientation =
5341 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5342#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005343 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005344#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005345 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005346 }
5347
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005348 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5349 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005350 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005351 }
5352
Aniket Kumar Lata8f270262019-05-08 15:56:56 -07005353 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
5354 if (ret >= 0) {
5355 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5356 adev->bt_sco_on = true;
5357 else
5358 adev->bt_sco_on = false;
5359 }
5360
David Linee3fe402017-03-13 10:00:42 -07005361 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5362 if (ret >= 0) {
5363 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005364 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005365 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5366 if (ret >= 0) {
5367 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005368 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005369 }
Eric Laurent99dab492017-06-17 15:19:08 -07005370 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005371 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5372 if (ret >= 0) {
5373 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005374 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005375 }
5376 }
5377 }
5378
5379 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5380 if (ret >= 0) {
5381 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005382 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005383 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5384 if (ret >= 0) {
5385 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005386 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005387 }
Eric Laurent99dab492017-06-17 15:19:08 -07005388 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005389 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5390 if (ret >= 0) {
5391 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005392 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005393 }
5394 }
5395 }
5396
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005397 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005398 audio_extn_ma_set_parameters(adev, parms);
5399
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005400 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5401 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005402 struct audio_usecase *usecase;
5403 struct listnode *node;
5404 list_for_each(node, &adev->usecase_list) {
5405 usecase = node_to_item(node, struct audio_usecase, list);
5406 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005407 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005408 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5409
5410 pthread_mutex_unlock(&adev->lock);
5411 lock_output_stream(usecase->stream.out);
5412 pthread_mutex_lock(&adev->lock);
5413 audio_extn_a2dp_set_handoff_mode(true);
5414 // force device switch to reconfigure encoder
5415 select_devices(adev, usecase->id);
5416 audio_extn_a2dp_set_handoff_mode(false);
5417 pthread_mutex_unlock(&usecase->stream.out->lock);
5418 break;
5419 }
5420 }
5421 }
5422
Eric Laurent5f4ca952018-10-19 17:33:43 -07005423 //FIXME: to be replaced by proper video capture properties API
5424 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5425 if (ret >= 0) {
5426 int camera_facing = CAMERA_FACING_BACK;
5427 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5428 camera_facing = CAMERA_FACING_FRONT;
5429 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5430 camera_facing = CAMERA_FACING_BACK;
5431 else {
5432 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5433 goto done;
5434 }
5435 adev->camera_orientation =
5436 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5437 struct audio_usecase *usecase;
5438 struct listnode *node;
5439 list_for_each(node, &adev->usecase_list) {
5440 usecase = node_to_item(node, struct audio_usecase, list);
5441 struct stream_in *in = usecase->stream.in;
5442 if (usecase->type == PCM_CAPTURE && in != NULL &&
5443 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5444 select_devices(adev, in->usecase);
5445 }
5446 }
5447 }
5448
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005449done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005450 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005451 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005452 ALOGV("%s: exit with code(%d)", __func__, status);
5453 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005454}
5455
5456static char* adev_get_parameters(const struct audio_hw_device *dev,
5457 const char *keys)
5458{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005459 struct audio_device *adev = (struct audio_device *)dev;
5460 struct str_parms *reply = str_parms_create();
5461 struct str_parms *query = str_parms_create_str(keys);
5462 char *str;
5463
5464 pthread_mutex_lock(&adev->lock);
5465
5466 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005467 audio_extn_a2dp_get_parameters(query, reply);
5468
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005469 str = str_parms_to_str(reply);
5470 str_parms_destroy(query);
5471 str_parms_destroy(reply);
5472
5473 pthread_mutex_unlock(&adev->lock);
5474 ALOGV("%s: exit: returns - %s", __func__, str);
5475 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476}
5477
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005478static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005479{
5480 return 0;
5481}
5482
Haynes Mathew George5191a852013-09-11 14:19:36 -07005483static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5484{
5485 int ret;
5486 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005487
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005488 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5489
Haynes Mathew George5191a852013-09-11 14:19:36 -07005490 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005491 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005492 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005493
Haynes Mathew George5191a852013-09-11 14:19:36 -07005494 return ret;
5495}
5496
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005497static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005498{
5499 return -ENOSYS;
5500}
5501
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005502static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5503 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005504{
5505 return -ENOSYS;
5506}
5507
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005508static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509{
5510 return -ENOSYS;
5511}
5512
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005513static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005514{
5515 return -ENOSYS;
5516}
5517
5518static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5519{
5520 struct audio_device *adev = (struct audio_device *)dev;
5521
5522 pthread_mutex_lock(&adev->lock);
5523 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005524 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005526 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5527 voice_is_in_call(adev)) {
5528 voice_stop_call(adev);
5529 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005530
5531 /*
5532 * After stopping the call, it must check if any active capture
5533 * activity device needs to be re-selected.
5534 */
5535 struct audio_usecase *usecase;
5536 struct listnode *node;
5537 list_for_each(node, &adev->usecase_list) {
5538 usecase = node_to_item(node, struct audio_usecase, list);
5539 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5540 select_devices_with_force_switch(adev, usecase->id, true);
5541 }
5542 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005544 }
5545 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005546
5547 audio_extn_extspk_set_mode(adev->extspk, mode);
5548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005549 return 0;
5550}
5551
5552static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5553{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005554 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005555 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005556
Eric Laurent2bafff12016-03-17 12:17:23 -07005557 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005558 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005559 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5560 ret = audio_extn_hfp_set_mic_mute(adev, state);
5561 } else {
5562 ret = voice_set_mic_mute(adev, state);
5563 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005564 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005565 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005566
5567 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568}
5569
5570static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5571{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005572 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005573 return 0;
5574}
5575
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005576static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005577 const struct audio_config *config)
5578{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005579 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005580
Eric Laurent74b55762017-07-09 17:04:53 -07005581 /* Don't know if USB HIFI in this context so use true to be conservative */
5582 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5583 true /*is_usb_hifi */) != 0)
5584 return 0;
5585
vivek mehtaa68fea62017-06-08 19:04:02 -07005586 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5587 config->sample_rate, config->format,
5588 channel_count,
5589 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590}
5591
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005592static bool adev_input_allow_hifi_record(struct audio_device *adev,
5593 audio_devices_t devices,
5594 audio_input_flags_t flags,
5595 audio_source_t source) {
5596 const bool allowed = true;
5597
5598 if (!audio_is_usb_in_device(devices))
5599 return !allowed;
5600
5601 switch (flags) {
5602 case AUDIO_INPUT_FLAG_NONE:
5603 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5604 break;
5605 default:
5606 return !allowed;
5607 }
5608
5609 switch (source) {
5610 case AUDIO_SOURCE_DEFAULT:
5611 case AUDIO_SOURCE_MIC:
5612 case AUDIO_SOURCE_UNPROCESSED:
5613 break;
5614 default:
5615 return !allowed;
5616 }
5617
5618 switch (adev->mode) {
5619 case 0:
5620 break;
5621 default:
5622 return !allowed;
5623 }
5624
5625 return allowed;
5626}
5627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005628static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005629 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005630 audio_devices_t devices,
5631 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005632 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005633 audio_input_flags_t flags,
5634 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005635 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005636{
5637 struct audio_device *adev = (struct audio_device *)dev;
5638 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005639 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005640 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005641 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005642 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005643 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5644 devices,
5645 flags,
5646 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005647 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5648 " sample_rate %u, channel_mask %#x, format %#x",
5649 __func__, flags, is_usb_dev, may_use_hifi_record,
5650 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005651 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005652
Andy Hungd9653bd2017-08-01 19:31:39 -07005653 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5654 return -ENOSYS;
5655 }
5656
Eric Laurent74b55762017-07-09 17:04:53 -07005657 if (!(is_usb_dev && may_use_hifi_record)) {
5658 if (config->sample_rate == 0)
5659 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5660 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5661 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5662 if (config->format == AUDIO_FORMAT_DEFAULT)
5663 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005664
Eric Laurent74b55762017-07-09 17:04:53 -07005665 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5666
5667 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5668 return -EINVAL;
5669 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005670
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005671 if (audio_extn_tfa_98xx_is_supported() &&
5672 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005673 return -EINVAL;
5674
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005675 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5676
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005677 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005678 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005680 in->stream.common.get_sample_rate = in_get_sample_rate;
5681 in->stream.common.set_sample_rate = in_set_sample_rate;
5682 in->stream.common.get_buffer_size = in_get_buffer_size;
5683 in->stream.common.get_channels = in_get_channels;
5684 in->stream.common.get_format = in_get_format;
5685 in->stream.common.set_format = in_set_format;
5686 in->stream.common.standby = in_standby;
5687 in->stream.common.dump = in_dump;
5688 in->stream.common.set_parameters = in_set_parameters;
5689 in->stream.common.get_parameters = in_get_parameters;
5690 in->stream.common.add_audio_effect = in_add_audio_effect;
5691 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5692 in->stream.set_gain = in_set_gain;
5693 in->stream.read = in_read;
5694 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005695 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005696 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005697 in->stream.set_microphone_direction = in_set_microphone_direction;
5698 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005699 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700
5701 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005702 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005704 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005705 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005706 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005707 in->direction = MIC_DIRECTION_UNSPECIFIED;
5708 in->zoom = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005709
Andy Hung88ce1d92018-10-29 18:31:12 -07005710 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005711 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5712 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5713 /* Force channel config requested to mono if incall
5714 record is being requested for only uplink/downlink */
5715 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5716 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5717 ret = -EINVAL;
5718 goto err_open;
5719 }
5720 }
5721
Haynes Mathew George569b7482017-05-08 14:44:27 -07005722 if (is_usb_dev && may_use_hifi_record) {
5723 /* HiFi record selects an appropriate format, channel, rate combo
5724 depending on sink capabilities*/
5725 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5726 &config->format,
5727 &in->supported_formats[0],
5728 MAX_SUPPORTED_FORMATS,
5729 &config->channel_mask,
5730 &in->supported_channel_masks[0],
5731 MAX_SUPPORTED_CHANNEL_MASKS,
5732 &config->sample_rate,
5733 &in->supported_sample_rates[0],
5734 MAX_SUPPORTED_SAMPLE_RATES);
5735 if (ret != 0) {
5736 ret = -EINVAL;
5737 goto err_open;
5738 }
Eric Laurent74b55762017-07-09 17:04:53 -07005739 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005740 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005741 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005742 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5743 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5744 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5745 bool ret_error = false;
5746 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5747 from HAL is 8_24
5748 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5749 8_24 return error indicating supported format is 8_24
5750 *> In case of any other source requesting 24 bit or float return error
5751 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005752
vivek mehta57ff9b52016-04-28 14:13:08 -07005753 on error flinger will retry with supported format passed
5754 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005755 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005756 config->format = AUDIO_FORMAT_PCM_16_BIT;
5757 ret_error = true;
5758 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5759 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5760 ret_error = true;
5761 }
5762
5763 if (ret_error) {
5764 ret = -EINVAL;
5765 goto err_open;
5766 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005767 }
5768
vivek mehta57ff9b52016-04-28 14:13:08 -07005769 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005770 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005772 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005773 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5774 if (config->sample_rate == 0)
5775 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5776 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5777 config->sample_rate != 8000) {
5778 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5779 ret = -EINVAL;
5780 goto err_open;
5781 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005782
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005783 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5784 config->format = AUDIO_FORMAT_PCM_16_BIT;
5785 ret = -EINVAL;
5786 goto err_open;
5787 }
5788
5789 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5790 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005791 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005792 } else if (is_usb_dev && may_use_hifi_record) {
5793 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5794 in->config = pcm_config_audio_capture;
5795 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005796 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5797 config->sample_rate,
5798 config->format,
5799 channel_count,
5800 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005801 in->config.period_size = buffer_size / frame_size;
5802 in->config.rate = config->sample_rate;
5803 in->af_period_multiplier = 1;
5804 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005805 } else {
5806 in->usecase = USECASE_AUDIO_RECORD;
5807 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005808 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005809 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005810#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005811 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005812#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005813 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005814 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005815 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005816 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005817 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5818 config->sample_rate,
5819 config->format,
5820 channel_count,
5821 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005822 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005823 in->config.rate = config->sample_rate;
5824 in->af_period_multiplier = 1;
5825 } else {
5826 // period size is left untouched for rt mode playback
5827 in->config = pcm_config_audio_capture_rt;
5828 in->af_period_multiplier = af_period_multiplier;
5829 }
5830 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5831 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005832 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005833 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5834 in->config = pcm_config_mmap_capture;
5835 in->stream.start = in_start;
5836 in->stream.stop = in_stop;
5837 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5838 in->stream.get_mmap_position = in_get_mmap_position;
5839 in->af_period_multiplier = 1;
5840 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005841 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005842 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005843 (config->sample_rate == 8000 ||
5844 config->sample_rate == 16000 ||
5845 config->sample_rate == 32000 ||
5846 config->sample_rate == 48000) &&
5847 channel_count == 1) {
5848 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5849 in->config = pcm_config_audio_capture;
5850 frame_size = audio_stream_in_frame_size(&in->stream);
5851 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5852 config->sample_rate,
5853 config->format,
5854 channel_count, false /*is_low_latency*/);
5855 in->config.period_size = buffer_size / frame_size;
5856 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5857 in->config.rate = config->sample_rate;
5858 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005859 } else {
5860 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005861 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005862 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5863 config->sample_rate,
5864 config->format,
5865 channel_count,
5866 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005867 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005868 in->config.rate = config->sample_rate;
5869 in->af_period_multiplier = 1;
5870 }
5871 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5872 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005873 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005875 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005876 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005877
Kevin Rocarda325aa22018-04-03 09:15:52 -07005878
5879 register_format(in->format, in->supported_formats);
5880 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5881 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5882
Andy Hungd13f0d32017-06-12 13:58:37 -07005883 in->error_log = error_log_create(
5884 ERROR_LOG_ENTRIES,
5885 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5886
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005887 /* This stream could be for sound trigger lab,
5888 get sound trigger pcm if present */
5889 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005890
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005891 lock_input_stream(in);
5892 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5893 pthread_mutex_lock(&adev->lock);
5894 in->card_status = adev->card_status;
5895 pthread_mutex_unlock(&adev->lock);
5896 pthread_mutex_unlock(&in->lock);
5897
vivek mehta4a824772017-06-08 19:05:49 -07005898 stream_app_type_cfg_init(&in->app_type_cfg);
5899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005900 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005901 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005902 return 0;
5903
5904err_open:
5905 free(in);
5906 *stream_in = NULL;
5907 return ret;
5908}
5909
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005910static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005911 struct audio_stream_in *stream)
5912{
Andy Hungd13f0d32017-06-12 13:58:37 -07005913 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005914 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005915
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005916 // must deregister from sndmonitor first to prevent races
5917 // between the callback and close_stream
5918 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005919 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005920
5921 error_log_destroy(in->error_log);
5922 in->error_log = NULL;
5923
Andy Hung0dbb52b2017-08-09 13:51:38 -07005924 pthread_mutex_destroy(&in->pre_lock);
5925 pthread_mutex_destroy(&in->lock);
5926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005927 free(stream);
5928
5929 return;
5930}
5931
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005932static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933{
5934 return 0;
5935}
5936
Andy Hung31aca912014-03-20 17:14:59 -07005937/* verifies input and output devices and their capabilities.
5938 *
5939 * This verification is required when enabling extended bit-depth or
5940 * sampling rates, as not all qcom products support it.
5941 *
5942 * Suitable for calling only on initialization such as adev_open().
5943 * It fills the audio_device use_case_table[] array.
5944 *
5945 * Has a side-effect that it needs to configure audio routing / devices
5946 * in order to power up the devices and read the device parameters.
5947 * It does not acquire any hw device lock. Should restore the devices
5948 * back to "normal state" upon completion.
5949 */
5950static int adev_verify_devices(struct audio_device *adev)
5951{
5952 /* enumeration is a bit difficult because one really wants to pull
5953 * the use_case, device id, etc from the hidden pcm_device_table[].
5954 * In this case there are the following use cases and device ids.
5955 *
5956 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5957 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005958 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005959 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5960 * [USECASE_AUDIO_RECORD] = {0, 0},
5961 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5962 * [USECASE_VOICE_CALL] = {2, 2},
5963 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005964 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005965 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5966 */
5967
5968 /* should be the usecases enabled in adev_open_input_stream() */
5969 static const int test_in_usecases[] = {
5970 USECASE_AUDIO_RECORD,
5971 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5972 };
5973 /* should be the usecases enabled in adev_open_output_stream()*/
5974 static const int test_out_usecases[] = {
5975 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5976 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5977 };
5978 static const usecase_type_t usecase_type_by_dir[] = {
5979 PCM_PLAYBACK,
5980 PCM_CAPTURE,
5981 };
5982 static const unsigned flags_by_dir[] = {
5983 PCM_OUT,
5984 PCM_IN,
5985 };
5986
5987 size_t i;
5988 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005989 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005990 char info[512]; /* for possible debug info */
5991
5992 for (dir = 0; dir < 2; ++dir) {
5993 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5994 const unsigned flags_dir = flags_by_dir[dir];
5995 const size_t testsize =
5996 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5997 const int *testcases =
5998 dir ? test_in_usecases : test_out_usecases;
5999 const audio_devices_t audio_device =
6000 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
6001
6002 for (i = 0; i < testsize; ++i) {
6003 const audio_usecase_t audio_usecase = testcases[i];
6004 int device_id;
6005 snd_device_t snd_device;
6006 struct pcm_params **pparams;
6007 struct stream_out out;
6008 struct stream_in in;
6009 struct audio_usecase uc_info;
6010 int retval;
6011
6012 pparams = &adev->use_case_table[audio_usecase];
6013 pcm_params_free(*pparams); /* can accept null input */
6014 *pparams = NULL;
6015
6016 /* find the device ID for the use case (signed, for error) */
6017 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
6018 if (device_id < 0)
6019 continue;
6020
6021 /* prepare structures for device probing */
6022 memset(&uc_info, 0, sizeof(uc_info));
6023 uc_info.id = audio_usecase;
6024 uc_info.type = usecase_type;
6025 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07006026 memset(&in, 0, sizeof(in));
6027 in.device = audio_device;
6028 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
6029 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07006030 }
6031 memset(&out, 0, sizeof(out));
6032 out.devices = audio_device; /* only field needed in select_devices */
6033 uc_info.stream.out = &out;
6034 uc_info.devices = audio_device;
6035 uc_info.in_snd_device = SND_DEVICE_NONE;
6036 uc_info.out_snd_device = SND_DEVICE_NONE;
6037 list_add_tail(&adev->usecase_list, &uc_info.list);
6038
6039 /* select device - similar to start_(in/out)put_stream() */
6040 retval = select_devices(adev, audio_usecase);
6041 if (retval >= 0) {
6042 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6043#if LOG_NDEBUG == 0
6044 if (*pparams) {
6045 ALOGV("%s: (%s) card %d device %d", __func__,
6046 dir ? "input" : "output", card_id, device_id);
6047 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006048 } else {
6049 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6050 }
6051#endif
6052 }
6053
6054 /* deselect device - similar to stop_(in/out)put_stream() */
6055 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006056 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006057 /* 2. Disable the rx device */
6058 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006059 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006060 list_remove(&uc_info.list);
6061 }
6062 }
Andy Hung31aca912014-03-20 17:14:59 -07006063 return 0;
6064}
6065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006066static int adev_close(hw_device_t *device)
6067{
Andy Hung31aca912014-03-20 17:14:59 -07006068 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006069 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006070
6071 if (!adev)
6072 return 0;
6073
6074 pthread_mutex_lock(&adev_init_lock);
6075
6076 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006077 audio_extn_snd_mon_unregister_listener(adev);
6078 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006079 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006080 audio_route_free(adev->audio_route);
6081 free(adev->snd_dev_ref_cnt);
6082 platform_deinit(adev->platform);
6083 audio_extn_extspk_deinit(adev->extspk);
6084 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006085 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006086 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6087 pcm_params_free(adev->use_case_table[i]);
6088 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006089 if (adev->adm_deinit)
6090 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006091 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006092 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006093 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006094
6095 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006097 return 0;
6098}
6099
Glenn Kasten4f993392014-05-14 07:30:48 -07006100/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6101 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6102 * just that it _might_ work.
6103 */
6104static int period_size_is_plausible_for_low_latency(int period_size)
6105{
6106 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006107 case 48:
6108 case 96:
6109 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006110 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006111 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006112 case 240:
6113 case 320:
6114 case 480:
6115 return 1;
6116 default:
6117 return 0;
6118 }
6119}
6120
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006121static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6122{
6123 int card;
6124 card_status_t status;
6125
6126 if (!parms)
6127 return;
6128
6129 if (parse_snd_card_status(parms, &card, &status) < 0)
6130 return;
6131
6132 pthread_mutex_lock(&adev->lock);
6133 bool valid_cb = (card == adev->snd_card);
6134 if (valid_cb) {
6135 if (adev->card_status != status) {
6136 adev->card_status = status;
6137 platform_snd_card_update(adev->platform, status);
6138 }
6139 }
6140 pthread_mutex_unlock(&adev->lock);
6141 return;
6142}
6143
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006144/* out and adev lock held */
6145static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6146{
6147 struct audio_usecase *uc_info;
6148 float left_p;
6149 float right_p;
6150 audio_devices_t devices;
6151
6152 uc_info = get_usecase_from_list(adev, out->usecase);
6153 if (uc_info == NULL) {
6154 ALOGE("%s: Could not find the usecase (%d) in the list",
6155 __func__, out->usecase);
6156 return -EINVAL;
6157 }
6158
6159 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6160 out->usecase, use_case_table[out->usecase]);
6161
6162 if (restore) {
6163 // restore A2DP device for active usecases and unmute if required
6164 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6165 !is_a2dp_device(uc_info->out_snd_device)) {
6166 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6167 select_devices(adev, uc_info->id);
6168 pthread_mutex_lock(&out->compr_mute_lock);
6169 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6170 (out->a2dp_compress_mute)) {
6171 out->a2dp_compress_mute = false;
6172 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6173 }
6174 pthread_mutex_unlock(&out->compr_mute_lock);
6175 }
6176 } else {
6177 // mute compress stream if suspended
6178 pthread_mutex_lock(&out->compr_mute_lock);
6179 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6180 (!out->a2dp_compress_mute)) {
6181 if (!out->standby) {
6182 ALOGD("%s: selecting speaker and muting stream", __func__);
6183 devices = out->devices;
6184 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6185 left_p = out->volume_l;
6186 right_p = out->volume_r;
6187 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6188 compress_pause(out->compr);
6189 set_compr_volume(&out->stream, 0.0f, 0.0f);
6190 out->a2dp_compress_mute = true;
6191 select_devices(adev, out->usecase);
6192 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6193 compress_resume(out->compr);
6194 out->devices = devices;
6195 out->volume_l = left_p;
6196 out->volume_r = right_p;
6197 }
6198 }
6199 pthread_mutex_unlock(&out->compr_mute_lock);
6200 }
6201 ALOGV("%s: exit", __func__);
6202 return 0;
6203}
6204
6205int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6206{
6207 int ret = 0;
6208
6209 lock_output_stream(out);
6210 pthread_mutex_lock(&adev->lock);
6211
6212 ret = check_a2dp_restore_l(adev, out, restore);
6213
6214 pthread_mutex_unlock(&adev->lock);
6215 pthread_mutex_unlock(&out->lock);
6216 return ret;
6217}
6218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006219static int adev_open(const hw_module_t *module, const char *name,
6220 hw_device_t **device)
6221{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006222 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006223
Eric Laurent2bafff12016-03-17 12:17:23 -07006224 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006225 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006226 pthread_mutex_lock(&adev_init_lock);
6227 if (audio_device_ref_count != 0) {
6228 *device = &adev->device.common;
6229 audio_device_ref_count++;
6230 ALOGV("%s: returning existing instance of adev", __func__);
6231 ALOGV("%s: exit", __func__);
6232 pthread_mutex_unlock(&adev_init_lock);
6233 return 0;
6234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006235 adev = calloc(1, sizeof(struct audio_device));
6236
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006237 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006239 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6240 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6241 adev->device.common.module = (struct hw_module_t *)module;
6242 adev->device.common.close = adev_close;
6243
6244 adev->device.init_check = adev_init_check;
6245 adev->device.set_voice_volume = adev_set_voice_volume;
6246 adev->device.set_master_volume = adev_set_master_volume;
6247 adev->device.get_master_volume = adev_get_master_volume;
6248 adev->device.set_master_mute = adev_set_master_mute;
6249 adev->device.get_master_mute = adev_get_master_mute;
6250 adev->device.set_mode = adev_set_mode;
6251 adev->device.set_mic_mute = adev_set_mic_mute;
6252 adev->device.get_mic_mute = adev_get_mic_mute;
6253 adev->device.set_parameters = adev_set_parameters;
6254 adev->device.get_parameters = adev_get_parameters;
6255 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6256 adev->device.open_output_stream = adev_open_output_stream;
6257 adev->device.close_output_stream = adev_close_output_stream;
6258 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260 adev->device.close_input_stream = adev_close_input_stream;
6261 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006262 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263
6264 /* Set the default route before the PCM stream is opened */
6265 pthread_mutex_lock(&adev->lock);
6266 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006267 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006269 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006270 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006271 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006272 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006273 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274 pthread_mutex_unlock(&adev->lock);
6275
6276 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006277 adev->platform = platform_init(adev);
6278 if (!adev->platform) {
6279 free(adev->snd_dev_ref_cnt);
6280 free(adev);
6281 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6282 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006283 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006284 return -EINVAL;
6285 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006286 adev->extspk = audio_extn_extspk_init(adev);
6287
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006288 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6289 if (adev->visualizer_lib == NULL) {
6290 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6291 } else {
6292 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6293 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006294 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006295 "visualizer_hal_start_output");
6296 adev->visualizer_stop_output =
6297 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6298 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006299 }
6300
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006301 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6302 if (adev->offload_effects_lib == NULL) {
6303 ALOGW("%s: DLOPEN failed for %s", __func__,
6304 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6305 } else {
6306 ALOGV("%s: DLOPEN successful for %s", __func__,
6307 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6308 adev->offload_effects_start_output =
6309 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6310 "offload_effects_bundle_hal_start_output");
6311 adev->offload_effects_stop_output =
6312 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6313 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006314 }
6315
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006316 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6317 if (adev->adm_lib == NULL) {
6318 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6319 } else {
6320 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6321 adev->adm_init = (adm_init_t)
6322 dlsym(adev->adm_lib, "adm_init");
6323 adev->adm_deinit = (adm_deinit_t)
6324 dlsym(adev->adm_lib, "adm_deinit");
6325 adev->adm_register_input_stream = (adm_register_input_stream_t)
6326 dlsym(adev->adm_lib, "adm_register_input_stream");
6327 adev->adm_register_output_stream = (adm_register_output_stream_t)
6328 dlsym(adev->adm_lib, "adm_register_output_stream");
6329 adev->adm_deregister_stream = (adm_deregister_stream_t)
6330 dlsym(adev->adm_lib, "adm_deregister_stream");
6331 adev->adm_request_focus = (adm_request_focus_t)
6332 dlsym(adev->adm_lib, "adm_request_focus");
6333 adev->adm_abandon_focus = (adm_abandon_focus_t)
6334 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006335 adev->adm_set_config = (adm_set_config_t)
6336 dlsym(adev->adm_lib, "adm_set_config");
6337 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6338 dlsym(adev->adm_lib, "adm_request_focus_v2");
6339 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6340 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6341 adev->adm_on_routing_change = (adm_on_routing_change_t)
6342 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006343 }
6344
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006345 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006346 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006348 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006349
Andy Hung31aca912014-03-20 17:14:59 -07006350 if (k_enable_extended_precision)
6351 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006352
Glenn Kasten4f993392014-05-14 07:30:48 -07006353 char value[PROPERTY_VALUE_MAX];
6354 int trial;
6355 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6356 trial = atoi(value);
6357 if (period_size_is_plausible_for_low_latency(trial)) {
6358 pcm_config_low_latency.period_size = trial;
6359 pcm_config_low_latency.start_threshold = trial / 4;
6360 pcm_config_low_latency.avail_min = trial / 4;
6361 configured_low_latency_capture_period_size = trial;
6362 }
6363 }
6364 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6365 trial = atoi(value);
6366 if (period_size_is_plausible_for_low_latency(trial)) {
6367 configured_low_latency_capture_period_size = trial;
6368 }
6369 }
6370
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006371 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6372
Eric Laurent5f4ca952018-10-19 17:33:43 -07006373 adev->camera_orientation = CAMERA_DEFAULT;
6374
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006375 // commented as full set of app type cfg is sent from platform
6376 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006377 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006378
6379 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6380 af_period_multiplier = atoi(value);
6381 if (af_period_multiplier < 0) {
6382 af_period_multiplier = 2;
6383 } else if (af_period_multiplier > 4) {
6384 af_period_multiplier = 4;
6385 }
6386 ALOGV("new period_multiplier = %d", af_period_multiplier);
6387 }
6388
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006389 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006390 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006391 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006392
vivek mehta1a9b7c02015-06-25 11:49:38 -07006393 pthread_mutex_unlock(&adev_init_lock);
6394
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006395 if (adev->adm_init)
6396 adev->adm_data = adev->adm_init();
6397
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006398 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006399 audio_extn_snd_mon_init();
6400 pthread_mutex_lock(&adev->lock);
6401 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6402 adev->card_status = CARD_STATUS_ONLINE;
6403 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006404 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006405
Eric Laurent2bafff12016-03-17 12:17:23 -07006406 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 return 0;
6408}
6409
6410static struct hw_module_methods_t hal_module_methods = {
6411 .open = adev_open,
6412};
6413
6414struct audio_module HAL_MODULE_INFO_SYM = {
6415 .common = {
6416 .tag = HARDWARE_MODULE_TAG,
6417 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6418 .hal_api_version = HARDWARE_HAL_API_VERSION,
6419 .id = AUDIO_HARDWARE_MODULE_ID,
6420 .name = "QCOM Audio HAL",
6421 .author = "Code Aurora Forum",
6422 .methods = &hal_module_methods,
6423 },
6424};