blob: 517351e39a1eb9215a8e57f27d634b9c990ff567 [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) &&
2884 !audio_extn_a2dp_is_ready()) {
2885 val = AUDIO_DEVICE_OUT_SPEAKER;
2886 }
2887
2888 /* To avoid a2dp to sco overlapping / BT device improper state
2889 * check with BT lib about a2dp streaming support before routing
2890 */
2891 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2892 if (!audio_extn_a2dp_is_ready()) {
juyuchen9baad392018-06-05 19:02:10 +08002893 if (val & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002894 //combo usecase just by pass a2dp
2895 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2896 bypass_a2dp = true;
2897 } else {
2898 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2899 /* update device to a2dp and don't route as BT returned error
2900 * However it is still possible a2dp routing called because
2901 * of current active device disconnection (like wired headset)
2902 */
2903 out->devices = val;
2904 pthread_mutex_unlock(&out->lock);
2905 pthread_mutex_unlock(&adev->lock);
2906 status = -ENOSYS;
2907 goto routing_fail;
2908 }
2909 }
2910 }
2911
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002912 audio_devices_t new_dev = val;
2913
2914 // Workaround: If routing to an non existing usb device, fail gracefully
2915 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002916 int card;
2917 if (audio_is_usb_out_device(new_dev) &&
2918 (card = get_alive_usb_card(parms)) >= 0) {
2919
2920 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002921 pthread_mutex_unlock(&adev->lock);
2922 pthread_mutex_unlock(&out->lock);
2923 status = -ENOSYS;
2924 goto routing_fail;
2925 }
2926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002927 /*
2928 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002929 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002930 * the select_devices(). But how do we undo this?
2931 *
2932 * For example, music playback is active on headset (deep-buffer usecase)
2933 * and if we go to ringtones and select a ringtone, low-latency usecase
2934 * will be started on headset+speaker. As we can't enable headset+speaker
2935 * and headset devices at the same time, select_devices() switches the music
2936 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2937 * So when the ringtone playback is completed, how do we undo the same?
2938 *
2939 * We are relying on the out_set_parameters() call on deep-buffer output,
2940 * once the ringtone playback is ended.
2941 * NOTE: We should not check if the current devices are same as new devices.
2942 * Because select_devices() must be called to switch back the music
2943 * playback to headset.
2944 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002945 if (new_dev != AUDIO_DEVICE_NONE) {
2946 bool same_dev = out->devices == new_dev;
2947 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002948
Eric Laurenta7657192014-10-09 21:09:33 -07002949 if (output_drives_call(adev, out)) {
Vignesh Kulothungana5c9da12017-11-10 11:41:24 -08002950 if (!voice_is_call_state_active(adev)) {
Eric Laurenta7657192014-10-09 21:09:33 -07002951 if (adev->mode == AUDIO_MODE_IN_CALL) {
2952 adev->current_call_output = out;
2953 ret = voice_start_call(adev);
2954 }
2955 } else {
2956 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002957 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002958 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002959 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002960
2961 if (!out->standby) {
2962 if (!same_dev) {
2963 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002964 // inform adm before actual routing to prevent glitches.
2965 if (adev->adm_on_routing_change) {
2966 adev->adm_on_routing_change(adev->adm_data,
2967 out->handle);
2968 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002969 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002970 if (!bypass_a2dp) {
2971 select_devices(adev, out->usecase);
2972 } else {
juyuchen9baad392018-06-05 19:02:10 +08002973 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
2974 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
2975 else
2976 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002977 select_devices(adev, out->usecase);
2978 out->devices = new_dev;
2979 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002980 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002981
2982 // on device switch force swap, lower functions will make sure
2983 // to check if swap is allowed or not.
2984
2985 if (!same_dev)
2986 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002987
2988 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2989 out->a2dp_compress_mute &&
2990 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2991 pthread_mutex_lock(&out->compr_mute_lock);
2992 out->a2dp_compress_mute = false;
2993 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2994 pthread_mutex_unlock(&out->compr_mute_lock);
2995 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002996 }
2997
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002998 }
2999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003001 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003002
3003 /*handles device and call state changes*/
3004 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003006 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003007
3008 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3009 parse_compress_metadata(out, parms);
3010 }
3011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003013 ALOGV("%s: exit: code(%d)", __func__, status);
3014 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015}
3016
Haynes Mathew George569b7482017-05-08 14:44:27 -07003017static bool stream_get_parameter_channels(struct str_parms *query,
3018 struct str_parms *reply,
3019 audio_channel_mask_t *supported_channel_masks) {
3020 int ret = -1;
Andy Hung64fdb452018-09-07 11:25:33 -07003021 char value[ARRAY_SIZE(channels_name_to_enum_table) * 32 /* max channel name size */];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003023 size_t i, j;
3024
3025 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
3026 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 value[0] = '\0';
3028 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003029 while (supported_channel_masks[i] != 0) {
3030 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
3031 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 if (!first) {
3033 strcat(value, "|");
3034 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003035 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 first = false;
3037 break;
3038 }
3039 }
3040 i++;
3041 }
3042 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003043 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003044 return ret >= 0;
3045}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003046
Haynes Mathew George569b7482017-05-08 14:44:27 -07003047static bool stream_get_parameter_formats(struct str_parms *query,
3048 struct str_parms *reply,
3049 audio_format_t *supported_formats) {
3050 int ret = -1;
3051 char value[256];
3052 int i;
3053
3054 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
3055 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003056 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07003057 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003058 case AUDIO_FORMAT_PCM_16_BIT:
3059 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
3060 break;
3061 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
3062 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
3063 break;
3064 case AUDIO_FORMAT_PCM_32_BIT:
3065 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
3066 break;
3067 default:
3068 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07003069 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003070 break;
3071 }
3072 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003073 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003074 return ret >= 0;
3075}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003076
Haynes Mathew George569b7482017-05-08 14:44:27 -07003077static bool stream_get_parameter_rates(struct str_parms *query,
3078 struct str_parms *reply,
3079 uint32_t *supported_sample_rates) {
3080
3081 int i;
3082 char value[256];
3083 int ret = -1;
3084 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
3085 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003086 value[0] = '\0';
3087 i=0;
3088 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003089 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003090 int avail = sizeof(value) - cursor;
3091 ret = snprintf(value + cursor, avail, "%s%d",
3092 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07003093 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003094 if (ret < 0 || ret >= avail) {
3095 // if cursor is at the last element of the array
3096 // overwrite with \0 is duplicate work as
3097 // snprintf already put a \0 in place.
3098 // else
3099 // we had space to write the '|' at value[cursor]
3100 // (which will be overwritten) or no space to fill
3101 // the first element (=> cursor == 0)
3102 value[cursor] = '\0';
3103 break;
3104 }
3105 cursor += ret;
3106 ++i;
3107 }
3108 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
3109 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003110 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07003111 return ret >= 0;
3112}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003113
Haynes Mathew George569b7482017-05-08 14:44:27 -07003114static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
3115{
3116 struct stream_out *out = (struct stream_out *)stream;
3117 struct str_parms *query = str_parms_create_str(keys);
3118 char *str;
3119 struct str_parms *reply = str_parms_create();
3120 bool replied = false;
3121 ALOGV("%s: enter: keys - %s", __func__, keys);
3122
3123 replied |= stream_get_parameter_channels(query, reply,
3124 &out->supported_channel_masks[0]);
3125 replied |= stream_get_parameter_formats(query, reply,
3126 &out->supported_formats[0]);
3127 replied |= stream_get_parameter_rates(query, reply,
3128 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003129 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 str = str_parms_to_str(reply);
3131 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07003132 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 }
3134 str_parms_destroy(query);
3135 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07003136 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 return str;
3138}
3139
3140static uint32_t out_get_latency(const struct audio_stream_out *stream)
3141{
Haynes Mathew George03c40102016-01-29 17:57:48 -08003142 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003144 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003146 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
3147 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003148 else if ((out->realtime) ||
3149 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003150 // since the buffer won't be filled up faster than realtime,
3151 // return a smaller number
3152 period_ms = (out->af_period_multiplier * out->config.period_size *
3153 1000) / (out->config.rate);
3154 hw_delay = platform_render_latency(out->usecase)/1000;
3155 return period_ms + hw_delay;
3156 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003157
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003158 latency = (out->config.period_count * out->config.period_size * 1000) /
3159 (out->config.rate);
3160
3161 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
3162 latency += audio_extn_a2dp_get_encoder_latency();
3163
3164 return latency;
3165}
3166
3167static int set_compr_volume(struct audio_stream_out *stream, float left,
3168 float right)
3169{
3170 struct stream_out *out = (struct stream_out *)stream;
3171 int volume[2];
3172 char mixer_ctl_name[128];
3173 struct audio_device *adev = out->dev;
3174 struct mixer_ctl *ctl;
3175 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
3176 PCM_PLAYBACK);
3177
3178 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3179 "Compress Playback %d Volume", pcm_device_id);
3180 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3181 if (!ctl) {
3182 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3183 __func__, mixer_ctl_name);
3184 return -EINVAL;
3185 }
3186 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
3187 __func__, mixer_ctl_name, left, right);
3188 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3189 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3190 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
3191
3192 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193}
3194
3195static int out_set_volume(struct audio_stream_out *stream, float left,
3196 float right)
3197{
Eric Laurenta9024de2013-04-04 09:19:12 -07003198 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003199 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003200
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003201 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07003202 /* only take left channel into account: the API is for stereo anyway */
3203 out->muted = (left == 0.0f);
3204 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003205 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003206 pthread_mutex_lock(&out->compr_mute_lock);
3207 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
3208 if (!out->a2dp_compress_mute)
3209 ret = set_compr_volume(stream, left, right);
3210 out->volume_l = left;
3211 out->volume_r = right;
3212 pthread_mutex_unlock(&out->compr_mute_lock);
3213 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07003214 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07003215 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
3216 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
3217 if (!out->standby) {
3218 // if in standby, cached volume will be sent after stream is opened
3219 audio_extn_utils_send_app_type_gain(out->dev,
3220 out->app_type_cfg.app_type,
3221 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07003222 }
vivek mehtaa68fea62017-06-08 19:04:02 -07003223 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07003224 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003225
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 return -ENOSYS;
3227}
3228
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003229// note: this call is safe only if the stream_cb is
3230// removed first in close_output_stream (as is done now).
3231static void out_snd_mon_cb(void * stream, struct str_parms * parms)
3232{
3233 if (!stream || !parms)
3234 return;
3235
3236 struct stream_out *out = (struct stream_out *)stream;
3237 struct audio_device *adev = out->dev;
3238
3239 card_status_t status;
3240 int card;
3241 if (parse_snd_card_status(parms, &card, &status) < 0)
3242 return;
3243
3244 pthread_mutex_lock(&adev->lock);
3245 bool valid_cb = (card == adev->snd_card);
3246 pthread_mutex_unlock(&adev->lock);
3247
3248 if (!valid_cb)
3249 return;
3250
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003251 lock_output_stream(out);
3252 if (out->card_status != status)
3253 out->card_status = status;
3254 pthread_mutex_unlock(&out->lock);
3255
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07003256 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
3257 use_case_table[out->usecase],
3258 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3259
3260 if (status == CARD_STATUS_OFFLINE)
3261 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003262
3263 return;
3264}
3265
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003266#ifdef NO_AUDIO_OUT
3267static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003268 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003269{
3270 struct stream_out *out = (struct stream_out *)stream;
3271
3272 /* No Output device supported other than BT for playback.
3273 * Sleep for the amount of buffer duration
3274 */
Eric Laurenta1478072015-09-21 17:21:52 -07003275 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05003276 usleep(bytes * 1000000 / audio_stream_out_frame_size(
3277 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003278 out_get_sample_rate(&out->stream.common));
3279 pthread_mutex_unlock(&out->lock);
3280 return bytes;
3281}
3282#endif
3283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3285 size_t bytes)
3286{
3287 struct stream_out *out = (struct stream_out *)stream;
3288 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07003289 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07003290 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291
Eric Laurenta1478072015-09-21 17:21:52 -07003292 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07003293 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07003294 const size_t frame_size = audio_stream_out_frame_size(stream);
3295 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07003296
Eric Laurent0e46adf2016-12-16 12:49:24 -08003297 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3298 error_code = ERROR_CODE_WRITE;
3299 goto exit;
3300 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003301
3302 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
3303 (audio_extn_a2dp_is_suspended())) {
juyuchen9baad392018-06-05 19:02:10 +08003304 if (!(out->devices & (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003305 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3306 ret = -EIO;
3307 goto exit;
3308 }
3309 }
3310 }
3311
Andy Hung572633e2019-02-19 11:58:24 -08003312 const bool was_in_standby = out->standby;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003314 out->standby = false;
Andy Hung241e36f2019-02-19 12:00:38 -08003315 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
3316
Eric Laurent150dbfe2013-02-27 14:31:02 -08003317 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07003319
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003320 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003322 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07003323 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 goto exit;
3325 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07003326
vivek mehta40125092017-08-21 18:48:51 -07003327 // after standby always force set last known cal step
3328 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
3329 ALOGD("%s: retry previous failed cal level set", __func__);
3330 send_gain_dep_calibration_l();
3331 pthread_mutex_unlock(&adev->lock);
Andy Hung572633e2019-02-19 11:58:24 -08003332
Andy Hung241e36f2019-02-19 12:00:38 -08003333 // log startup time in ms.
3334 simple_stats_log(
3335 &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Andy Hung572633e2019-02-19 11:58:24 -08003336 out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003339 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003340 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003341 if (out->send_new_metadata) {
3342 ALOGVV("send new gapless metadata");
3343 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3344 out->send_new_metadata = 0;
3345 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003346 unsigned int avail;
3347 struct timespec tstamp;
3348 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
3349 /* Do not limit write size if the available frames count is unknown */
3350 if (ret != 0) {
3351 avail = bytes;
3352 }
3353 if (avail == 0) {
3354 ret = 0;
3355 } else {
Andy Hung572633e2019-02-19 11:58:24 -08003356 // check for compressed format underrun, essentially an empty buffer check
3357 // for a lack of better measurement.
3358 if (!was_in_standby && avail == out->kernel_buffer_size) {
3359 ALOGW("%s: compressed buffer empty (underrun)", __func__);
3360 simple_stats_log(&out->fifo_underruns, 1.); // Note: log one frame for compressed.
3361 }
3362
Eric Laurentb49b3f62016-02-29 17:59:49 -08003363 if (avail > bytes) {
3364 avail = bytes;
3365 }
3366 ret = compress_write(out->compr, buffer, avail);
3367 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
3368 __func__, avail, ret);
3369 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003370
Eric Laurent6e895242013-09-05 16:10:57 -07003371 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
3373 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08003374 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003375 compress_start(out->compr);
3376 out->playback_started = 1;
3377 out->offload_state = OFFLOAD_STATE_PLAYING;
3378 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003379 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07003380 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07003381 } else {
3382 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07003383 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07003385 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003386 return ret;
3387 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07003388 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003389 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003390 size_t bytes_to_write = bytes;
3391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003392 if (out->muted)
3393 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07003394 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003395 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003396 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3397 int16_t *src = (int16_t *)buffer;
3398 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003399
Eric Laurentad2dde92017-09-20 18:27:31 -07003400 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
3401 out->format != AUDIO_FORMAT_PCM_16_BIT,
3402 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003403
Eric Laurentad2dde92017-09-20 18:27:31 -07003404 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
3405 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
3406 }
3407 bytes_to_write /= 2;
3408 }
Andy Hung572633e2019-02-19 11:58:24 -08003409
3410 // Note: since out_get_presentation_position() is called alternating with out_write()
3411 // by AudioFlinger, we can check underruns using the prior timestamp read.
3412 // (Alternately we could check if the buffer is empty using pcm_get_htimestamp().
3413 if (out->last_fifo_valid) {
3414 // compute drain to see if there is an underrun.
3415 const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call
3416 const int64_t frames_by_time =
3417 (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND;
3418 const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining;
3419
3420 if (underrun > 0) {
3421 simple_stats_log(&out->fifo_underruns, underrun);
3422
3423 ALOGW("%s: underrun(%lld) "
3424 "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)",
3425 __func__,
3426 (long long)out->fifo_underruns.n,
3427 (long long)frames_by_time,
3428 (long long)out->last_fifo_frames_remaining);
3429 }
3430 out->last_fifo_valid = false; // we're writing below, mark fifo info as stale.
3431 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003432
Glenn Kasten5a59dff2018-02-22 08:05:35 -08003433 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003434 request_out_focus(out, ns);
3435
3436 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003437 if (use_mmap) {
Eric Laurentad2dde92017-09-20 18:27:31 -07003438 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003439 } else {
3440 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3441 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
3442 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
3443 size_t frame_size = channel_count * bytes_per_sample;
3444 size_t frame_count = bytes_to_write / frame_size;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003445
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08003446 bool force_haptic_path =
3447 property_get_bool("vendor.audio.test_haptic", false);
3448
3449 // extract Haptics data from Audio buffer
3450 bool alloc_haptic_buffer = false;
3451 int haptic_channel_count = adev->haptics_config.channels;
3452 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
3453 size_t audio_frame_size = frame_size - haptic_frame_size;
3454 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
3455
3456 if (adev->haptic_buffer == NULL) {
3457 alloc_haptic_buffer = true;
3458 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
3459 free(adev->haptic_buffer);
3460 adev->haptic_buffer_size = 0;
3461 alloc_haptic_buffer = true;
3462 }
3463
3464 if (alloc_haptic_buffer) {
3465 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
3466 adev->haptic_buffer_size = total_haptic_buffer_size;
3467 }
3468
3469 size_t src_index = 0, aud_index = 0, hap_index = 0;
3470 uint8_t *audio_buffer = (uint8_t *)buffer;
3471 uint8_t *haptic_buffer = adev->haptic_buffer;
3472
3473 // This is required for testing only. This works for stereo data only.
3474 // One channel is fed to audio stream and other to haptic stream for testing.
3475 if (force_haptic_path) {
3476 audio_frame_size = haptic_frame_size = bytes_per_sample;
3477 }
3478
3479 for (size_t i = 0; i < frame_count; i++) {
3480 for (size_t j = 0; j < audio_frame_size; j++)
3481 audio_buffer[aud_index++] = audio_buffer[src_index++];
3482
3483 for (size_t j = 0; j < haptic_frame_size; j++)
3484 haptic_buffer[hap_index++] = audio_buffer[src_index++];
3485 }
3486
3487 // This is required for testing only.
3488 // Discard haptic channel data.
3489 if (force_haptic_path) {
3490 src_index += haptic_frame_size;
3491 }
3492
3493 // write to audio pipeline
3494 ret = pcm_write(out->pcm,
3495 (void *)audio_buffer,
3496 frame_count * audio_frame_size);
3497
3498 // write to haptics pipeline
3499 if (adev->haptic_pcm)
3500 ret = pcm_write(adev->haptic_pcm,
3501 (void *)adev->haptic_buffer,
3502 frame_count * haptic_frame_size);
3503
3504 } else {
3505 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
3506 }
3507 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003508 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07003509 } else {
3510 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 }
3513
3514exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07003515 // For PCM we always consume the buffer and return #bytes regardless of ret.
3516 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003517 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07003518 }
Andy Hung7401c7c2016-09-21 12:41:21 -07003519 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07003520
Andy Hung7401c7c2016-09-21 12:41:21 -07003521 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07003522 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07003523 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3524 ALOGE_IF(out->pcm != NULL,
3525 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07003526 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003527 // usleep not guaranteed for values over 1 second but we don't limit here.
3528 }
3529 }
Andy Hungda9b56b2016-09-16 20:06:35 -07003530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 pthread_mutex_unlock(&out->lock);
3532
3533 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07003534 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07003535 if (sleeptime_us != 0)
3536 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537 }
3538 return bytes;
3539}
3540
3541static int out_get_render_position(const struct audio_stream_out *stream,
3542 uint32_t *dsp_frames)
3543{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544 struct stream_out *out = (struct stream_out *)stream;
3545 *dsp_frames = 0;
3546 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07003547 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003548 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003549 unsigned long frames = 0;
3550 // TODO: check return value
3551 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
3552 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003553 ALOGVV("%s rendered frames %d sample_rate %d",
3554 __func__, *dsp_frames, out->sample_rate);
3555 }
3556 pthread_mutex_unlock(&out->lock);
3557 return 0;
3558 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003559 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003560}
3561
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003562static int out_add_audio_effect(const struct audio_stream *stream __unused,
3563 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564{
3565 return 0;
3566}
3567
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003568static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3569 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570{
3571 return 0;
3572}
3573
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003574static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3575 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003577 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578}
3579
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003580static int out_get_presentation_position(const struct audio_stream_out *stream,
3581 uint64_t *frames, struct timespec *timestamp)
3582{
3583 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003584 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07003585 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003586
Eric Laurenta1478072015-09-21 17:21:52 -07003587 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003588
Eric Laurent949a0892013-09-20 09:20:13 -07003589 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3590 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08003591 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003592 compress_get_tstamp(out->compr, &dsp_frames,
3593 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003594 // Adjustment accounts for A2DP encoder latency with offload usecases
3595 // Note: Encoder latency is returned in ms.
3596 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3597 unsigned long offset =
3598 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3599 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3600 }
Eric Laurent949a0892013-09-20 09:20:13 -07003601 ALOGVV("%s rendered frames %ld sample_rate %d",
3602 __func__, dsp_frames, out->sample_rate);
3603 *frames = dsp_frames;
3604 ret = 0;
3605 /* this is the best we can do */
3606 clock_gettime(CLOCK_MONOTONIC, timestamp);
3607 }
3608 } else {
3609 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003610 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003611 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
Andy Hung572633e2019-02-19 11:58:24 -08003612
3613 // pcm_get_htimestamp() computes the available frames by comparing
3614 // the alsa driver hw_ptr and the appl_ptr levels.
3615 // In underrun, the hw_ptr may keep running and report an excessively
3616 // large number available number.
3617 if (avail > out->kernel_buffer_size) {
3618 ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!",
3619 __func__, avail, out->kernel_buffer_size);
3620 avail = out->kernel_buffer_size;
3621 out->last_fifo_frames_remaining = 0;
3622 } else {
3623 out->last_fifo_frames_remaining = out->kernel_buffer_size - avail;
3624 }
3625 out->last_fifo_valid = true;
3626 out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp);
3627
3628 int64_t signed_frames = out->written - out->last_fifo_frames_remaining;
3629
3630 ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu",
3631 __func__, (long long)signed_frames, avail, out->kernel_buffer_size);
3632
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003633 // This adjustment accounts for buffering after app processor.
3634 // It is based on estimated DSP latency per use case, rather than exact.
3635 signed_frames -=
3636 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3637
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003638 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3639 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3640 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3641 signed_frames -=
3642 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3643 }
3644
Eric Laurent949a0892013-09-20 09:20:13 -07003645 // It would be unusual for this value to be negative, but check just in case ...
3646 if (signed_frames >= 0) {
3647 *frames = signed_frames;
3648 ret = 0;
3649 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003650 }
3651 }
3652 }
3653
3654 pthread_mutex_unlock(&out->lock);
3655
3656 return ret;
3657}
3658
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659static int out_set_callback(struct audio_stream_out *stream,
3660 stream_callback_t callback, void *cookie)
3661{
3662 struct stream_out *out = (struct stream_out *)stream;
3663
3664 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003665 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 out->offload_callback = callback;
3667 out->offload_cookie = cookie;
3668 pthread_mutex_unlock(&out->lock);
3669 return 0;
3670}
3671
3672static int out_pause(struct audio_stream_out* stream)
3673{
3674 struct stream_out *out = (struct stream_out *)stream;
3675 int status = -ENOSYS;
3676 ALOGV("%s", __func__);
3677 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003678 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3680 status = compress_pause(out->compr);
3681 out->offload_state = OFFLOAD_STATE_PAUSED;
3682 }
3683 pthread_mutex_unlock(&out->lock);
3684 }
3685 return status;
3686}
3687
3688static int out_resume(struct audio_stream_out* stream)
3689{
3690 struct stream_out *out = (struct stream_out *)stream;
3691 int status = -ENOSYS;
3692 ALOGV("%s", __func__);
3693 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3694 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003695 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003696 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3697 status = compress_resume(out->compr);
3698 out->offload_state = OFFLOAD_STATE_PLAYING;
3699 }
3700 pthread_mutex_unlock(&out->lock);
3701 }
3702 return status;
3703}
3704
3705static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3706{
3707 struct stream_out *out = (struct stream_out *)stream;
3708 int status = -ENOSYS;
3709 ALOGV("%s", __func__);
3710 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003711 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003712 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3713 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3714 else
3715 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3716 pthread_mutex_unlock(&out->lock);
3717 }
3718 return status;
3719}
3720
3721static int out_flush(struct audio_stream_out* stream)
3722{
3723 struct stream_out *out = (struct stream_out *)stream;
3724 ALOGV("%s", __func__);
3725 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003726 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003727 stop_compressed_output_l(out);
3728 pthread_mutex_unlock(&out->lock);
3729 return 0;
3730 }
3731 return -ENOSYS;
3732}
3733
Eric Laurent0e46adf2016-12-16 12:49:24 -08003734static int out_stop(const struct audio_stream_out* stream)
3735{
3736 struct stream_out *out = (struct stream_out *)stream;
3737 struct audio_device *adev = out->dev;
3738 int ret = -ENOSYS;
3739
3740 ALOGV("%s", __func__);
3741 pthread_mutex_lock(&adev->lock);
3742 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3743 out->playback_started && out->pcm != NULL) {
3744 pcm_stop(out->pcm);
3745 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003746 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003747 }
3748 pthread_mutex_unlock(&adev->lock);
3749 return ret;
3750}
3751
3752static int out_start(const struct audio_stream_out* stream)
3753{
3754 struct stream_out *out = (struct stream_out *)stream;
3755 struct audio_device *adev = out->dev;
3756 int ret = -ENOSYS;
3757
3758 ALOGV("%s", __func__);
3759 pthread_mutex_lock(&adev->lock);
3760 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3761 !out->playback_started && out->pcm != NULL) {
3762 ret = start_output_stream(out);
3763 if (ret == 0) {
3764 out->playback_started = true;
3765 }
3766 }
3767 pthread_mutex_unlock(&adev->lock);
3768 return ret;
3769}
3770
Phil Burkbc991042017-02-24 08:06:44 -08003771/*
3772 * Modify config->period_count based on min_size_frames
3773 */
3774static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3775{
3776 int periodCountRequested = (min_size_frames + config->period_size - 1)
3777 / config->period_size;
3778 int periodCount = MMAP_PERIOD_COUNT_MIN;
3779
3780 ALOGV("%s original config.period_size = %d config.period_count = %d",
3781 __func__, config->period_size, config->period_count);
3782
3783 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3784 periodCount *= 2;
3785 }
3786 config->period_count = periodCount;
3787
3788 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3789}
3790
Phil Burk51e6bc42019-03-25 10:23:35 -07003791// Read offset for the positional timestamp from a persistent vendor property.
3792// This is to workaround apparent inaccuracies in the timing information that
3793// is used by the AAudio timing model. The inaccuracies can cause glitches.
3794static int64_t get_mmap_out_time_offset() {
3795 const int32_t kDefaultOffsetMicros = 0;
3796 int32_t mmap_time_offset_micros = property_get_int32(
3797 "persist.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
3798 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
3799 return mmap_time_offset_micros * (int64_t)1000;
3800}
3801
Eric Laurent0e46adf2016-12-16 12:49:24 -08003802static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3803 int32_t min_size_frames,
3804 struct audio_mmap_buffer_info *info)
3805{
3806 struct stream_out *out = (struct stream_out *)stream;
3807 struct audio_device *adev = out->dev;
3808 int ret = 0;
3809 unsigned int offset1;
3810 unsigned int frames1;
3811 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003812 uint32_t mmap_size;
3813 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003814
3815 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003816 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003817 pthread_mutex_lock(&adev->lock);
3818
3819 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003820 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003821 ret = -EINVAL;
3822 goto exit;
3823 }
3824 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003825 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003826 ret = -ENOSYS;
3827 goto exit;
3828 }
3829 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3830 if (out->pcm_device_id < 0) {
3831 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3832 __func__, out->pcm_device_id, out->usecase);
3833 ret = -EINVAL;
3834 goto exit;
3835 }
Phil Burkbc991042017-02-24 08:06:44 -08003836
3837 adjust_mmap_period_count(&out->config, min_size_frames);
3838
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3840 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3841 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3842 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3843 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3844 step = "open";
3845 ret = -ENODEV;
3846 goto exit;
3847 }
3848 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3849 if (ret < 0) {
3850 step = "begin";
3851 goto exit;
3852 }
3853 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003854 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003855 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003856 ret = platform_get_mmap_data_fd(adev->platform,
3857 out->pcm_device_id, 0 /*playback*/,
3858 &info->shared_memory_fd,
3859 &mmap_size);
3860 if (ret < 0) {
3861 // Fall back to non exclusive mode
3862 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3863 } else {
3864 if (mmap_size < buffer_size) {
3865 step = "mmap";
3866 goto exit;
3867 }
3868 // FIXME: indicate exclusive mode support by returning a negative buffer size
3869 info->buffer_size_frames *= -1;
3870 }
3871 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003872
3873 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3874 if (ret < 0) {
3875 step = "commit";
3876 goto exit;
3877 }
Phil Burkbc991042017-02-24 08:06:44 -08003878
Phil Burk51e6bc42019-03-25 10:23:35 -07003879 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
3880
Phil Burkbc991042017-02-24 08:06:44 -08003881 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003882 ret = 0;
3883
3884 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3885 __func__, info->shared_memory_address, info->buffer_size_frames);
3886
3887exit:
3888 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003889 if (out->pcm == NULL) {
3890 ALOGE("%s: %s - %d", __func__, step, ret);
3891 } else {
3892 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003893 pcm_close(out->pcm);
3894 out->pcm = NULL;
3895 }
3896 }
3897 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003898 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003899 return ret;
3900}
3901
3902static int out_get_mmap_position(const struct audio_stream_out *stream,
3903 struct audio_mmap_position *position)
3904{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003905 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003906 struct stream_out *out = (struct stream_out *)stream;
3907 ALOGVV("%s", __func__);
3908 if (position == NULL) {
3909 return -EINVAL;
3910 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003911 lock_output_stream(out);
3912 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3913 out->pcm == NULL) {
3914 ret = -ENOSYS;
3915 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003916 }
3917
3918 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003919 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003920 if (ret < 0) {
3921 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003922 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003923 }
Phil Burk51e6bc42019-03-25 10:23:35 -07003924 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
3925 + out->mmap_time_offset_nanos;
3926
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003927exit:
3928 pthread_mutex_unlock(&out->lock);
3929 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003930}
3931
3932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003933/** audio_stream_in implementation **/
3934static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3935{
3936 struct stream_in *in = (struct stream_in *)stream;
3937
3938 return in->config.rate;
3939}
3940
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003941static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942{
3943 return -ENOSYS;
3944}
3945
3946static size_t in_get_buffer_size(const struct audio_stream *stream)
3947{
3948 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003949 return in->config.period_size * in->af_period_multiplier *
3950 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951}
3952
3953static uint32_t in_get_channels(const struct audio_stream *stream)
3954{
3955 struct stream_in *in = (struct stream_in *)stream;
3956
3957 return in->channel_mask;
3958}
3959
vivek mehta4ed66e62016-04-15 23:33:34 -07003960static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961{
vivek mehta4ed66e62016-04-15 23:33:34 -07003962 struct stream_in *in = (struct stream_in *)stream;
3963 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964}
3965
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003966static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967{
3968 return -ENOSYS;
3969}
3970
3971static int in_standby(struct audio_stream *stream)
3972{
3973 struct stream_in *in = (struct stream_in *)stream;
3974 struct audio_device *adev = in->dev;
3975 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003976 bool do_stop = true;
3977
Eric Laurent994a6932013-07-17 11:51:42 -07003978 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003979
3980 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003981
3982 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003983 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003984 audio_extn_sound_trigger_stop_lab(in);
3985 in->standby = true;
3986 }
3987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003989 if (adev->adm_deregister_stream)
3990 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3991
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003992 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003994 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003995 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003996 in->capture_started = false;
3997 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003998 if (in->pcm) {
3999 pcm_close(in->pcm);
4000 in->pcm = NULL;
4001 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05004002 adev->enable_voicerx = false;
4003 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08004004 if (do_stop) {
4005 status = stop_input_stream(in);
4006 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004007 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 }
4009 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07004010 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011 return status;
4012}
4013
Andy Hungd13f0d32017-06-12 13:58:37 -07004014static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015{
Andy Hungd13f0d32017-06-12 13:58:37 -07004016 struct stream_in *in = (struct stream_in *)stream;
4017
4018 // We try to get the lock for consistency,
4019 // but it isn't necessary for these variables.
4020 // If we're not in standby, we may be blocked on a read.
4021 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
4022 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
4023 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
4024 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
4025
Andy Hung241e36f2019-02-19 12:00:38 -08004026 char buffer[256]; // for statistics formatting
4027 if (in->start_latency_ms.n > 0) {
4028 simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer));
4029 dprintf(fd, " Start latency ms: %s\n", buffer);
4030 }
4031
Andy Hungd13f0d32017-06-12 13:58:37 -07004032 if (locked) {
4033 pthread_mutex_unlock(&in->lock);
4034 }
4035
4036 // dump error info
4037 (void)error_log_dump(
4038 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039 return 0;
4040}
4041
4042static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
4043{
4044 struct stream_in *in = (struct stream_in *)stream;
4045 struct audio_device *adev = in->dev;
4046 struct str_parms *parms;
4047 char *str;
4048 char value[32];
4049 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07004050 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051
Eric Laurent994a6932013-07-17 11:51:42 -07004052 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053 parms = str_parms_create_str(kvpairs);
4054
4055 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
4056
Eric Laurenta1478072015-09-21 17:21:52 -07004057 lock_input_stream(in);
4058
Eric Laurent150dbfe2013-02-27 14:31:02 -08004059 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 if (ret >= 0) {
4061 val = atoi(value);
4062 /* no audio source uses val == 0 */
4063 if ((in->source != val) && (val != 0)) {
4064 in->source = val;
4065 }
4066 }
4067
4068 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07004069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070 if (ret >= 0) {
4071 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07004072 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004073
4074 // Workaround: If routing to an non existing usb device, fail gracefully
4075 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07004076 int card;
4077 if (audio_is_usb_in_device(val) &&
4078 (card = get_alive_usb_card(parms)) >= 0) {
4079
4080 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07004081 status = -ENOSYS;
4082 } else {
4083
4084 in->device = val;
4085 /* If recording is in progress, change the tx device to new device */
4086 if (!in->standby) {
4087 ALOGV("update input routing change");
4088 // inform adm before actual routing to prevent glitches.
4089 if (adev->adm_on_routing_change) {
4090 adev->adm_on_routing_change(adev->adm_data,
4091 in->capture_handle);
4092 }
4093 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07004094 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004095 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 }
4097 }
4098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004100 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101
4102 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07004103 ALOGV("%s: exit: status(%d)", __func__, status);
4104 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105}
4106
Haynes Mathew George569b7482017-05-08 14:44:27 -07004107static char* in_get_parameters(const struct audio_stream *stream,
4108 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109{
Haynes Mathew George569b7482017-05-08 14:44:27 -07004110 struct stream_in *in = (struct stream_in *)stream;
4111 struct str_parms *query = str_parms_create_str(keys);
4112 char *str;
4113 struct str_parms *reply = str_parms_create();
4114 bool replied = false;
4115
4116 ALOGV("%s: enter: keys - %s", __func__, keys);
4117 replied |= stream_get_parameter_channels(query, reply,
4118 &in->supported_channel_masks[0]);
4119 replied |= stream_get_parameter_formats(query, reply,
4120 &in->supported_formats[0]);
4121 replied |= stream_get_parameter_rates(query, reply,
4122 &in->supported_sample_rates[0]);
4123 if (replied) {
4124 str = str_parms_to_str(reply);
4125 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07004126 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07004127 }
4128 str_parms_destroy(query);
4129 str_parms_destroy(reply);
4130 ALOGV("%s: exit: returns - %s", __func__, str);
4131 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132}
4133
Eric Laurent51f3c662018-04-10 18:21:34 -07004134static int in_set_gain(struct audio_stream_in *stream, float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135{
Eric Laurent51f3c662018-04-10 18:21:34 -07004136 struct stream_in *in = (struct stream_in *)stream;
4137 char mixer_ctl_name[128];
4138 struct mixer_ctl *ctl;
4139 int ctl_value;
4140
4141 ALOGV("%s: gain %f", __func__, gain);
4142
4143 if (stream == NULL)
4144 return -EINVAL;
4145
4146 /* in_set_gain() only used to silence MMAP capture for now */
4147 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
4148 return -ENOSYS;
4149
4150 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
4151
4152 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
4153 if (!ctl) {
4154 ALOGW("%s: Could not get ctl for mixer cmd - %s",
4155 __func__, mixer_ctl_name);
4156 return -ENOSYS;
4157 }
4158
4159 if (gain < RECORD_GAIN_MIN)
4160 gain = RECORD_GAIN_MIN;
4161 else if (gain > RECORD_GAIN_MAX)
4162 gain = RECORD_GAIN_MAX;
4163 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
4164
4165 mixer_ctl_set_value(ctl, 0, ctl_value);
4166 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167}
4168
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004169static void in_snd_mon_cb(void * stream, struct str_parms * parms)
4170{
4171 if (!stream || !parms)
4172 return;
4173
4174 struct stream_in *in = (struct stream_in *)stream;
4175 struct audio_device *adev = in->dev;
4176
4177 card_status_t status;
4178 int card;
4179 if (parse_snd_card_status(parms, &card, &status) < 0)
4180 return;
4181
4182 pthread_mutex_lock(&adev->lock);
4183 bool valid_cb = (card == adev->snd_card);
4184 pthread_mutex_unlock(&adev->lock);
4185
4186 if (!valid_cb)
4187 return;
4188
4189 lock_input_stream(in);
4190 if (in->card_status != status)
4191 in->card_status = status;
4192 pthread_mutex_unlock(&in->lock);
4193
4194 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
4195 use_case_table[in->usecase],
4196 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4197
4198 // a better solution would be to report error back to AF and let
4199 // it put the stream to standby
4200 if (status == CARD_STATUS_OFFLINE)
4201 in_standby(&in->stream.common);
4202
4203 return;
4204}
4205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
4207 size_t bytes)
4208{
4209 struct stream_in *in = (struct stream_in *)stream;
4210 struct audio_device *adev = in->dev;
4211 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07004212 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07004213 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214
Eric Laurenta1478072015-09-21 17:21:52 -07004215 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004216 const size_t frame_size = audio_stream_in_frame_size(stream);
4217 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07004218
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004219 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004220 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004221 /* Read from sound trigger HAL */
4222 audio_extn_sound_trigger_read(in, buffer, bytes);
4223 pthread_mutex_unlock(&in->lock);
4224 return bytes;
4225 }
4226
Eric Laurent0e46adf2016-12-16 12:49:24 -08004227 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
4228 ret = -ENOSYS;
4229 goto exit;
4230 }
4231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 if (in->standby) {
Andy Hung241e36f2019-02-19 12:00:38 -08004233 const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC);
4234
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004235 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004237 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004238 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239 goto exit;
4240 }
4241 in->standby = 0;
Andy Hung241e36f2019-02-19 12:00:38 -08004242
4243 // log startup time in ms.
4244 simple_stats_log(
4245 &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247
Andy Hungd13f0d32017-06-12 13:58:37 -07004248 // errors that occur here are read errors.
4249 error_code = ERROR_CODE_READ;
4250
Haynes Mathew George03c40102016-01-29 17:57:48 -08004251 //what's the duration requested by the client?
4252 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
4253 in->config.rate;
4254 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004255
Haynes Mathew George03c40102016-01-29 17:57:48 -08004256 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08004258 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004259 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07004260 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004261 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004262 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004263 if (ret < 0) {
4264 ALOGE("Failed to read w/err %s", strerror(errno));
4265 ret = -errno;
4266 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004267 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4268 if (bytes % 4 == 0) {
4269 /* data from DSP comes in 24_8 format, convert it to 8_24 */
4270 int_buf_stream = buffer;
4271 for (size_t itt=0; itt < bytes/4 ; itt++) {
4272 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07004273 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07004274 } else {
4275 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
4276 ret = -EINVAL;
4277 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07004278 }
4279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 }
4281
Haynes Mathew George03c40102016-01-29 17:57:48 -08004282 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004283
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004284 /*
4285 * Instead of writing zeroes here, we could trust the hardware
4286 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004287 * 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 -08004288 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08004289 if (ret == 0 && adev->mic_muted &&
4290 !voice_is_in_call_rec_stream(in) &&
4291 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07004293 in->frames_muted += frames;
4294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295
4296exit:
4297 pthread_mutex_unlock(&in->lock);
4298
4299 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07004300 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004301 in_standby(&in->stream.common);
4302 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07004303 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08004304 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07004305 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08004306 }
4307 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07004308 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 }
4310 return bytes;
4311}
4312
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004313static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314{
4315 return 0;
4316}
4317
Andy Hung6ebe5962016-01-15 17:46:57 -08004318static int in_get_capture_position(const struct audio_stream_in *stream,
4319 int64_t *frames, int64_t *time)
4320{
4321 if (stream == NULL || frames == NULL || time == NULL) {
4322 return -EINVAL;
4323 }
4324 struct stream_in *in = (struct stream_in *)stream;
4325 int ret = -ENOSYS;
4326
4327 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004328 // note: ST sessions do not close the alsa pcm driver synchronously
4329 // on standby. Therefore, we may return an error even though the
4330 // pcm stream is still opened.
4331 if (in->standby) {
4332 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
4333 "%s stream in standby but pcm not NULL for non ST session", __func__);
4334 goto exit;
4335 }
Andy Hung6ebe5962016-01-15 17:46:57 -08004336 if (in->pcm) {
4337 struct timespec timestamp;
4338 unsigned int avail;
4339 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
4340 *frames = in->frames_read + avail;
4341 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
4342 ret = 0;
4343 }
4344 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08004345exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08004346 pthread_mutex_unlock(&in->lock);
4347 return ret;
4348}
4349
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004350static int add_remove_audio_effect(const struct audio_stream *stream,
4351 effect_handle_t effect,
4352 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004354 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004355 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004356 int status = 0;
4357 effect_descriptor_t desc;
4358
4359 status = (*effect)->get_descriptor(effect, &desc);
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004360 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
4361
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004362 if (status != 0)
4363 return status;
4364
Eric Laurenta1478072015-09-21 17:21:52 -07004365 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004366 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07004367 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07004368 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07004369 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004370 in->enable_aec != enable &&
4371 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
4372 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004373 if (!enable)
4374 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07004375 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
4376 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
4377 adev->enable_voicerx = enable;
4378 struct audio_usecase *usecase;
4379 struct listnode *node;
4380 list_for_each(node, &adev->usecase_list) {
4381 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07004382 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07004383 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05004384 }
4385 }
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004386 if (!in->standby
4387 && enable_disable_effect(in->dev, in, EFFECT_AEC, enable) == -ENOSYS)
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004388 select_devices(in->dev, in->usecase);
4389 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004390 if (in->enable_ns != enable &&
4391 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
4392 in->enable_ns = enable;
Vignesh Kulothungan64698822018-01-23 11:25:18 -08004393 if (!in->standby) {
4394 if (in->source != AUDIO_SOURCE_VOICE_COMMUNICATION
4395 || enable_disable_effect(in->dev, in, EFFECT_NS, enable) == -ENOSYS)
4396 select_devices(in->dev, in->usecase);
4397 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07004398 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004399 pthread_mutex_unlock(&in->dev->lock);
4400 pthread_mutex_unlock(&in->lock);
4401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 return 0;
4403}
4404
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004405static int in_add_audio_effect(const struct audio_stream *stream,
4406 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004407{
Eric Laurent994a6932013-07-17 11:51:42 -07004408 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004409 return add_remove_audio_effect(stream, effect, true);
4410}
4411
4412static int in_remove_audio_effect(const struct audio_stream *stream,
4413 effect_handle_t effect)
4414{
Eric Laurent994a6932013-07-17 11:51:42 -07004415 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07004416 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417}
4418
Eric Laurent0e46adf2016-12-16 12:49:24 -08004419static int in_stop(const struct audio_stream_in* stream)
4420{
4421 struct stream_in *in = (struct stream_in *)stream;
4422 struct audio_device *adev = in->dev;
4423
4424 int ret = -ENOSYS;
4425 ALOGV("%s", __func__);
4426 pthread_mutex_lock(&adev->lock);
4427 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4428 in->capture_started && in->pcm != NULL) {
4429 pcm_stop(in->pcm);
4430 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08004431 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004432 }
4433 pthread_mutex_unlock(&adev->lock);
4434 return ret;
4435}
4436
4437static int in_start(const struct audio_stream_in* stream)
4438{
4439 struct stream_in *in = (struct stream_in *)stream;
4440 struct audio_device *adev = in->dev;
4441 int ret = -ENOSYS;
4442
4443 ALOGV("%s in %p", __func__, in);
4444 pthread_mutex_lock(&adev->lock);
4445 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
4446 !in->capture_started && in->pcm != NULL) {
4447 if (!in->capture_started) {
4448 ret = start_input_stream(in);
4449 if (ret == 0) {
4450 in->capture_started = true;
4451 }
4452 }
4453 }
4454 pthread_mutex_unlock(&adev->lock);
4455 return ret;
4456}
4457
Phil Burk8a6a1652019-03-25 10:15:59 -07004458// Read offset for the positional timestamp from a persistent vendor property.
4459// This is to workaround apparent inaccuracies in the timing information that
4460// is used by the AAudio timing model. The inaccuracies can cause glitches.
Phil Burkc4714fc2019-02-16 22:28:11 -08004461static int64_t in_get_mmap_time_offset() {
Phil Burk8a6a1652019-03-25 10:15:59 -07004462 const int32_t kDefaultOffsetMicros = 0;
Phil Burkc4714fc2019-02-16 22:28:11 -08004463 int32_t mmap_time_offset_micros = property_get_int32(
Phil Burk8a6a1652019-03-25 10:15:59 -07004464 "persist.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkc4714fc2019-02-16 22:28:11 -08004465 ALOGI("in_get_mmap_time_offset set to %d micros", mmap_time_offset_micros);
4466 return mmap_time_offset_micros * (int64_t)1000;
4467}
4468
Eric Laurent0e46adf2016-12-16 12:49:24 -08004469static int in_create_mmap_buffer(const struct audio_stream_in *stream,
4470 int32_t min_size_frames,
4471 struct audio_mmap_buffer_info *info)
4472{
4473 struct stream_in *in = (struct stream_in *)stream;
4474 struct audio_device *adev = in->dev;
4475 int ret = 0;
4476 unsigned int offset1;
4477 unsigned int frames1;
4478 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07004479 uint32_t mmap_size;
4480 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004481
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004482 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004483 pthread_mutex_lock(&adev->lock);
4484 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08004485
Eric Laurent0e46adf2016-12-16 12:49:24 -08004486 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004487 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004488 ret = -EINVAL;
4489 goto exit;
4490 }
4491 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08004492 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004493 ALOGV("%s in %p", __func__, in);
4494 ret = -ENOSYS;
4495 goto exit;
4496 }
4497 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
4498 if (in->pcm_device_id < 0) {
4499 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
4500 __func__, in->pcm_device_id, in->usecase);
4501 ret = -EINVAL;
4502 goto exit;
4503 }
Phil Burkbc991042017-02-24 08:06:44 -08004504
4505 adjust_mmap_period_count(&in->config, min_size_frames);
4506
Eric Laurent0e46adf2016-12-16 12:49:24 -08004507 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
4508 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
4509 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
4510 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
4511 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
4512 step = "open";
4513 ret = -ENODEV;
4514 goto exit;
4515 }
4516
4517 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
4518 if (ret < 0) {
4519 step = "begin";
4520 goto exit;
4521 }
4522 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07004523 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004524 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07004525 ret = platform_get_mmap_data_fd(adev->platform,
4526 in->pcm_device_id, 1 /*capture*/,
4527 &info->shared_memory_fd,
4528 &mmap_size);
4529 if (ret < 0) {
4530 // Fall back to non exclusive mode
4531 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
4532 } else {
4533 if (mmap_size < buffer_size) {
4534 step = "mmap";
4535 goto exit;
4536 }
4537 // FIXME: indicate exclusive mode support by returning a negative buffer size
4538 info->buffer_size_frames *= -1;
4539 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08004540
Haynes Mathew George96483a22017-03-28 14:52:47 -07004541 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004542
4543 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
4544 if (ret < 0) {
4545 step = "commit";
4546 goto exit;
4547 }
4548
Phil Burkc4714fc2019-02-16 22:28:11 -08004549 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
4550
Phil Burkbc991042017-02-24 08:06:44 -08004551 in->standby = false;
4552 ret = 0;
4553
Eric Laurent0e46adf2016-12-16 12:49:24 -08004554 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
4555 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004556
4557exit:
4558 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08004559 if (in->pcm == NULL) {
4560 ALOGE("%s: %s - %d", __func__, step, ret);
4561 } else {
4562 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08004563 pcm_close(in->pcm);
4564 in->pcm = NULL;
4565 }
4566 }
4567 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004568 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004569 return ret;
4570}
4571
4572static int in_get_mmap_position(const struct audio_stream_in *stream,
4573 struct audio_mmap_position *position)
4574{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004575 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004576 struct stream_in *in = (struct stream_in *)stream;
4577 ALOGVV("%s", __func__);
4578 if (position == NULL) {
4579 return -EINVAL;
4580 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004581 lock_input_stream(in);
4582 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
4583 in->pcm == NULL) {
4584 ret = -ENOSYS;
4585 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004586 }
4587 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004588 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004589 if (ret < 0) {
4590 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004591 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004592 }
Phil Burk8a6a1652019-03-25 10:15:59 -07004593 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts)
4594 + in->mmap_time_offset_nanos;
Phil Burkc4714fc2019-02-16 22:28:11 -08004595
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08004596exit:
4597 pthread_mutex_unlock(&in->lock);
4598 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004599}
4600
jiabin8962a4d2018-03-19 18:21:24 -07004601static int in_get_active_microphones(const struct audio_stream_in *stream,
4602 struct audio_microphone_characteristic_t *mic_array,
4603 size_t *mic_count) {
4604 struct stream_in *in = (struct stream_in *)stream;
4605 struct audio_device *adev = in->dev;
4606 ALOGVV("%s", __func__);
4607
4608 lock_input_stream(in);
4609 pthread_mutex_lock(&adev->lock);
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004610 int ret = platform_get_active_microphones(adev->platform,
jiabin8962a4d2018-03-19 18:21:24 -07004611 audio_channel_count_from_in_mask(in->channel_mask),
Aniket Kumar Latadebab2b2018-04-30 20:20:25 -07004612 in->usecase, mic_array, mic_count);
jiabin8962a4d2018-03-19 18:21:24 -07004613 pthread_mutex_unlock(&adev->lock);
4614 pthread_mutex_unlock(&in->lock);
4615
4616 return ret;
4617}
4618
4619static int adev_get_microphones(const struct audio_hw_device *dev,
4620 struct audio_microphone_characteristic_t *mic_array,
4621 size_t *mic_count) {
4622 struct audio_device *adev = (struct audio_device *)dev;
4623 ALOGVV("%s", __func__);
4624
4625 pthread_mutex_lock(&adev->lock);
4626 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
4627 pthread_mutex_unlock(&adev->lock);
4628
4629 return ret;
4630}
Eric Laurent0e46adf2016-12-16 12:49:24 -08004631
Paul McLean57530d52018-12-17 08:24:21 -07004632static int in_set_microphone_direction(const struct audio_stream_in *stream,
4633 audio_microphone_direction_t dir) {
justinwengc6347db2019-02-21 18:49:00 +08004634 struct stream_in *in = (struct stream_in *)stream;
4635
4636 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4637
4638 in->direction = dir;
4639
4640 if (in->standby)
4641 return 0;
4642
4643 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLean57530d52018-12-17 08:24:21 -07004644}
4645
4646static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinwengc6347db2019-02-21 18:49:00 +08004647 struct stream_in *in = (struct stream_in *)stream;
4648
4649 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4650
4651 if (zoom > 1.0 || zoom < -1.0)
4652 return -EINVAL;
4653
4654 in->zoom = zoom;
4655
4656 if (in->standby)
4657 return 0;
4658
4659 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLean57530d52018-12-17 08:24:21 -07004660}
4661
juyuchenba338cd2019-01-21 11:57:17 +08004662static void in_update_sink_metadata(struct audio_stream_in *stream,
4663 const struct sink_metadata *sink_metadata) {
4664
4665 if (stream == NULL
4666 || sink_metadata == NULL
4667 || sink_metadata->tracks == NULL) {
4668 return;
4669 }
4670
4671 int error = 0;
4672 struct stream_in *in = (struct stream_in *)stream;
4673 struct audio_device *adev = in->dev;
4674 audio_devices_t device = AUDIO_DEVICE_NONE;
4675
4676 if (sink_metadata->track_count != 0)
4677 device = sink_metadata->tracks->dest_device;
4678
4679 lock_input_stream(in);
4680 pthread_mutex_lock(&adev->lock);
4681 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
4682
4683 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
4684 && device != AUDIO_DEVICE_NONE
4685 && adev->voice_tx_output != NULL) {
4686 /* Use the rx device from afe-proxy record to route voice call because
4687 there is no routing if tx device is on primary hal and rx device
4688 is on other hal during voice call. */
4689 adev->voice_tx_output->devices = device;
4690
4691 if (!voice_is_call_state_active(adev)) {
4692 if (adev->mode == AUDIO_MODE_IN_CALL) {
4693 adev->current_call_output = adev->voice_tx_output;
4694 error = voice_start_call(adev);
4695 if (error != 0)
4696 ALOGE("%s: start voice call failed %d", __func__, error);
4697 }
4698 } else {
4699 adev->current_call_output = adev->voice_tx_output;
4700 voice_update_devices_for_all_voice_usecases(adev);
4701 }
4702 }
4703
4704 pthread_mutex_unlock(&adev->lock);
4705 pthread_mutex_unlock(&in->lock);
4706}
4707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004708static int adev_open_output_stream(struct audio_hw_device *dev,
4709 audio_io_handle_t handle,
4710 audio_devices_t devices,
4711 audio_output_flags_t flags,
4712 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07004713 struct audio_stream_out **stream_out,
4714 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715{
4716 struct audio_device *adev = (struct audio_device *)dev;
4717 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004718 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004719 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
4720 bool is_usb_dev = audio_is_usb_out_device(devices) &&
4721 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004722 bool force_haptic_path =
4723 property_get_bool("vendor.audio.test_haptic", false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724
Andy Hungd9653bd2017-08-01 19:31:39 -07004725 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
4726 return -ENOSYS;
4727 }
4728
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004729 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
4730 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08004731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004732 *stream_out = NULL;
4733 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
4734
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004735 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
4736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737 if (devices == AUDIO_DEVICE_NONE)
4738 devices = AUDIO_DEVICE_OUT_SPEAKER;
4739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 out->flags = flags;
4741 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07004742 out->dev = adev;
Eric Laurentc4aef752013-09-12 17:45:53 -07004743 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004744 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004745
4746 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004747 if ((is_hdmi || is_usb_dev) &&
4748 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
4749 (flags == AUDIO_OUTPUT_FLAG_NONE ||
4750 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07004751 audio_format_t req_format = config->format;
4752 audio_channel_mask_t req_channel_mask = config->channel_mask;
4753 uint32_t req_sample_rate = config->sample_rate;
4754
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004755 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004756 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004757 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004758 if (config->sample_rate == 0)
4759 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07004760 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07004761 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
4762 if (config->format == AUDIO_FORMAT_DEFAULT)
4763 config->format = AUDIO_FORMAT_PCM_16_BIT;
4764 } else if (is_usb_dev) {
4765 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
4766 &config->format,
4767 &out->supported_formats[0],
4768 MAX_SUPPORTED_FORMATS,
4769 &config->channel_mask,
4770 &out->supported_channel_masks[0],
4771 MAX_SUPPORTED_CHANNEL_MASKS,
4772 &config->sample_rate,
4773 &out->supported_sample_rates[0],
4774 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004775 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004776 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004777 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004778 if (ret != 0) {
4779 // For MMAP NO IRQ, allow conversions in ADSP
4780 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4781 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004782
Eric Laurentab805ee2018-03-30 12:20:38 -07004783 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4784 config->sample_rate = req_sample_rate;
4785 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4786 config->channel_mask = req_channel_mask;
4787 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4788 config->format = req_format;
4789 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004790
Haynes Mathew George569b7482017-05-08 14:44:27 -07004791 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004792 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004793 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004794 if (is_hdmi) {
4795 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4796 out->config = pcm_config_hdmi_multi;
4797 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4798 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4799 out->config = pcm_config_mmap_playback;
4800 out->stream.start = out_start;
4801 out->stream.stop = out_stop;
4802 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4803 out->stream.get_mmap_position = out_get_mmap_position;
4804 } else {
4805 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4806 out->config = pcm_config_hifi;
4807 }
4808
4809 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004810 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004811 if (is_hdmi) {
4812 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4813 audio_bytes_per_sample(out->format));
4814 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004815 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004816 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004817 pthread_mutex_lock(&adev->lock);
4818 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4819 pthread_mutex_unlock(&adev->lock);
4820
4821 // reject offload during card offline to allow
4822 // fallback to s/w paths
4823 if (offline) {
4824 ret = -ENODEV;
4825 goto error_open;
4826 }
4827
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004828 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4829 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4830 ALOGE("%s: Unsupported Offload information", __func__);
4831 ret = -EINVAL;
4832 goto error_open;
4833 }
4834 if (!is_supported_format(config->offload_info.format)) {
4835 ALOGE("%s: Unsupported audio format", __func__);
4836 ret = -EINVAL;
4837 goto error_open;
4838 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004839 out->sample_rate = config->offload_info.sample_rate;
4840 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4841 out->channel_mask = config->offload_info.channel_mask;
4842 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4843 out->channel_mask = config->channel_mask;
4844 else
4845 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4846
4847 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004848
4849 out->compr_config.codec = (struct snd_codec *)
4850 calloc(1, sizeof(struct snd_codec));
4851
4852 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004853
4854 out->stream.set_callback = out_set_callback;
4855 out->stream.pause = out_pause;
4856 out->stream.resume = out_resume;
4857 out->stream.drain = out_drain;
4858 out->stream.flush = out_flush;
4859
4860 out->compr_config.codec->id =
4861 get_snd_codec_id(config->offload_info.format);
4862 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4863 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004864 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004865 out->compr_config.codec->bit_rate =
4866 config->offload_info.bit_rate;
4867 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004868 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004869 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4870
4871 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4872 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004873
4874 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004875 create_offload_callback_thread(out);
4876 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4877 __func__, config->offload_info.version,
4878 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004879 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4880 switch (config->sample_rate) {
4881 case 0:
4882 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4883 break;
4884 case 8000:
4885 case 16000:
4886 case 48000:
4887 out->sample_rate = config->sample_rate;
4888 break;
4889 default:
4890 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4891 config->sample_rate);
4892 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4893 ret = -EINVAL;
4894 goto error_open;
4895 }
4896 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4897 switch (config->channel_mask) {
4898 case AUDIO_CHANNEL_NONE:
4899 case AUDIO_CHANNEL_OUT_STEREO:
4900 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4901 break;
4902 default:
4903 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4904 config->channel_mask);
4905 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4906 ret = -EINVAL;
4907 goto error_open;
4908 }
4909 switch (config->format) {
4910 case AUDIO_FORMAT_DEFAULT:
4911 case AUDIO_FORMAT_PCM_16_BIT:
4912 out->format = AUDIO_FORMAT_PCM_16_BIT;
4913 break;
4914 default:
4915 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4916 config->format);
4917 config->format = AUDIO_FORMAT_PCM_16_BIT;
4918 ret = -EINVAL;
4919 goto error_open;
4920 }
4921
4922 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004923 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004924 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004925 case 0:
4926 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4927 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004928 case 8000:
4929 case 16000:
4930 case 48000:
4931 out->sample_rate = config->sample_rate;
4932 break;
4933 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004934 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4935 config->sample_rate);
4936 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4937 ret = -EINVAL;
4938 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004939 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004940 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4941 switch (config->channel_mask) {
4942 case AUDIO_CHANNEL_NONE:
4943 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4944 break;
4945 case AUDIO_CHANNEL_OUT_STEREO:
4946 out->channel_mask = config->channel_mask;
4947 break;
4948 default:
4949 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4950 config->channel_mask);
4951 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4952 ret = -EINVAL;
4953 break;
4954 }
4955 switch (config->format) {
4956 case AUDIO_FORMAT_DEFAULT:
4957 out->format = AUDIO_FORMAT_PCM_16_BIT;
4958 break;
4959 case AUDIO_FORMAT_PCM_16_BIT:
4960 out->format = config->format;
4961 break;
4962 default:
4963 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4964 config->format);
4965 config->format = AUDIO_FORMAT_PCM_16_BIT;
4966 ret = -EINVAL;
4967 break;
4968 }
4969 if (ret != 0)
4970 goto error_open;
4971
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004972 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4973 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004974 out->config.rate = out->sample_rate;
4975 out->config.channels =
4976 audio_channel_count_from_out_mask(out->channel_mask);
4977 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004978 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004979 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4980 switch (config->sample_rate) {
4981 case 0:
4982 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4983 break;
4984 case 8000:
4985 case 16000:
4986 case 32000:
4987 case 48000:
4988 out->sample_rate = config->sample_rate;
4989 break;
4990 default:
4991 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4992 config->sample_rate);
4993 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4994 ret = -EINVAL;
4995 break;
4996 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004997 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004998 switch (config->channel_mask) {
4999 case AUDIO_CHANNEL_NONE:
5000 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5001 break;
5002 case AUDIO_CHANNEL_OUT_STEREO:
5003 out->channel_mask = config->channel_mask;
5004 break;
5005 default:
5006 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
5007 config->channel_mask);
5008 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
5009 ret = -EINVAL;
5010 break;
5011 }
5012 switch (config->format) {
5013 case AUDIO_FORMAT_DEFAULT:
5014 out->format = AUDIO_FORMAT_PCM_16_BIT;
5015 break;
5016 case AUDIO_FORMAT_PCM_16_BIT:
5017 out->format = config->format;
5018 break;
5019 default:
5020 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
5021 config->format);
5022 config->format = AUDIO_FORMAT_PCM_16_BIT;
5023 ret = -EINVAL;
5024 break;
5025 }
5026 if (ret != 0)
5027 goto error_open;
5028
vivek mehtaa68fea62017-06-08 19:04:02 -07005029 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07005030 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
5031 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005032 out->config.rate = out->sample_rate;
5033 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07005034 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005035 out->sample_rate,
5036 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07005037 out->config.channels,
5038 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005039 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07005040 out->config.period_size = buffer_size / frame_size;
5041 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
5042 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005043 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005044 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07005045 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
5046 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005047 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07005048 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
5049 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005050 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07005051 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005052 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005053 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005054 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08005055 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
5056 out->config = pcm_config_mmap_playback;
5057 out->stream.start = out_start;
5058 out->stream.stop = out_stop;
5059 out->stream.create_mmap_buffer = out_create_mmap_buffer;
5060 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005061 } else {
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005062 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5063 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
5064 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
5065 if (adev->haptic_pcm_device_id < 0) {
5066 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
5067 __func__, adev->haptic_pcm_device_id, out->usecase);
5068 ret = -ENOSYS;
5069 goto error_open;
5070 }
5071 out->config = pcm_config_haptics_audio;
5072 if (force_haptic_path)
5073 adev->haptics_config = pcm_config_haptics_audio;
5074 else
5075 adev->haptics_config = pcm_config_haptics;
5076 } else {
5077 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
5078 out->config = pcm_config_low_latency;
5079 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07005080 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005081
5082 if (config->sample_rate == 0) {
5083 out->sample_rate = out->config.rate;
5084 } else {
5085 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07005086 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005087
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005088 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
5089 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
5090 } else {
5091 out->channel_mask = config->channel_mask;
5092 }
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005093
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005094 if (config->format == AUDIO_FORMAT_DEFAULT)
5095 out->format = audio_format_from_pcm_format(out->config.format);
5096 else if (!audio_is_linear_pcm(config->format)) {
5097 config->format = AUDIO_FORMAT_PCM_16_BIT;
5098 ret = -EINVAL;
5099 goto error_open;
5100 } else {
5101 out->format = config->format;
5102 }
5103
5104 out->config.rate = out->sample_rate;
Vignesh Kulothungan019d19b2019-01-23 11:09:18 -08005105
5106 if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
5107 out->config.channels =
5108 audio_channel_count_from_out_mask(out->channel_mask &
5109 ~AUDIO_CHANNEL_HAPTIC_ALL);
5110
5111 if (force_haptic_path) {
5112 out->config.channels = 1;
5113 adev->haptics_config.channels = 1;
5114 } else {
5115 adev->haptics_config.channels =
5116 audio_channel_count_from_out_mask(out->channel_mask &
5117 AUDIO_CHANNEL_HAPTIC_ALL);
5118 }
5119 } else {
5120 out->config.channels =
5121 audio_channel_count_from_out_mask(out->channel_mask);
5122 }
5123
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005124 if (out->format != audio_format_from_pcm_format(out->config.format)) {
5125 out->config.format = pcm_format_from_audio_format(out->format);
5126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005127 }
Kevin Rocard50eff892017-05-02 16:52:05 -07005128
5129 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
5130 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07005131 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07005132 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
5133 __func__, config->sample_rate, config->format, config->channel_mask);
5134 config->sample_rate = out->sample_rate;
5135 config->format = out->format;
5136 config->channel_mask = out->channel_mask;
5137 ret = -EINVAL;
5138 goto error_open;
5139 }
5140
Andy Hung6fcba9c2014-03-18 11:53:32 -07005141 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
5142 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005143
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005144 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005145 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005146 adev->primary_output = out;
5147 else {
5148 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005149 ret = -EEXIST;
5150 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005151 }
5152 }
5153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005154 /* Check if this usecase is already existing */
5155 pthread_mutex_lock(&adev->lock);
5156 if (get_usecase_from_list(adev, out->usecase) != NULL) {
5157 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005158 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005159 ret = -EEXIST;
5160 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005161 }
5162 pthread_mutex_unlock(&adev->lock);
5163
5164 out->stream.common.get_sample_rate = out_get_sample_rate;
5165 out->stream.common.set_sample_rate = out_set_sample_rate;
5166 out->stream.common.get_buffer_size = out_get_buffer_size;
5167 out->stream.common.get_channels = out_get_channels;
5168 out->stream.common.get_format = out_get_format;
5169 out->stream.common.set_format = out_set_format;
5170 out->stream.common.standby = out_standby;
5171 out->stream.common.dump = out_dump;
5172 out->stream.common.set_parameters = out_set_parameters;
5173 out->stream.common.get_parameters = out_get_parameters;
5174 out->stream.common.add_audio_effect = out_add_audio_effect;
5175 out->stream.common.remove_audio_effect = out_remove_audio_effect;
5176 out->stream.get_latency = out_get_latency;
5177 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005178#ifdef NO_AUDIO_OUT
5179 out->stream.write = out_write_for_no_output;
5180#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07005182#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005183 out->stream.get_render_position = out_get_render_position;
5184 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005185 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005186
Eric Laurent0e46adf2016-12-16 12:49:24 -08005187 if (out->realtime)
5188 out->af_period_multiplier = af_period_multiplier;
5189 else
5190 out->af_period_multiplier = 1;
5191
Andy Hung572633e2019-02-19 11:58:24 -08005192 out->kernel_buffer_size = out->config.period_size * out->config.period_count;
5193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005194 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07005195 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005196 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005198 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005199 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005200 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
5201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005202 config->format = out->stream.common.get_format(&out->stream.common);
5203 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
5204 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
5205
Kevin Rocarda325aa22018-04-03 09:15:52 -07005206 register_format(out->format, out->supported_formats);
5207 register_channel_mask(out->channel_mask, out->supported_channel_masks);
5208 register_sample_rate(out->sample_rate, out->supported_sample_rates);
5209
Andy Hunga452b0a2017-03-15 14:51:15 -07005210 out->error_log = error_log_create(
5211 ERROR_LOG_ENTRIES,
5212 1000000000 /* aggregate consecutive identical errors within one second in ns */);
5213
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005214 /*
5215 By locking output stream before registering, we allow the callback
5216 to update stream's state only after stream's initial state is set to
5217 adev state.
5218 */
5219 lock_output_stream(out);
5220 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
5221 pthread_mutex_lock(&adev->lock);
5222 out->card_status = adev->card_status;
5223 pthread_mutex_unlock(&adev->lock);
5224 pthread_mutex_unlock(&out->lock);
5225
vivek mehta4a824772017-06-08 19:05:49 -07005226 stream_app_type_cfg_init(&out->app_type_cfg);
5227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005229
Eric Laurent994a6932013-07-17 11:51:42 -07005230 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005231 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005232
5233error_open:
5234 free(out);
5235 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07005236 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005237 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005238}
5239
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005240static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241 struct audio_stream_out *stream)
5242{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005243 struct stream_out *out = (struct stream_out *)stream;
5244 struct audio_device *adev = out->dev;
5245
Eric Laurent994a6932013-07-17 11:51:42 -07005246 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005247
5248 // must deregister from sndmonitor first to prevent races
5249 // between the callback and close_stream
5250 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005251 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005252 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
5253 destroy_offload_callback_thread(out);
5254
5255 if (out->compr_config.codec != NULL)
5256 free(out->compr_config.codec);
5257 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005258
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005259 out->a2dp_compress_mute = false;
5260
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07005261 if (adev->voice_tx_output == out)
5262 adev->voice_tx_output = NULL;
5263
Andy Hunga452b0a2017-03-15 14:51:15 -07005264 error_log_destroy(out->error_log);
5265 out->error_log = NULL;
5266
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005267 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005268 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005269 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005270 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07005271 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005272}
5273
5274static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
5275{
5276 struct audio_device *adev = (struct audio_device *)dev;
5277 struct str_parms *parms;
5278 char *str;
5279 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005280 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005281 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07005282 int status = 0;
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005283 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005284
Joe Onorato188b6222016-03-01 11:02:27 -08005285 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005286
5287 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005288
5289 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005290 status = voice_set_parameters(adev, parms);
5291 if (status != 0) {
5292 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005293 }
5294
5295 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
5296 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07005297 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005298 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5299 adev->bluetooth_nrec = true;
5300 else
5301 adev->bluetooth_nrec = false;
5302 }
5303
5304 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
5305 if (ret >= 0) {
5306 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
5307 adev->screen_off = false;
5308 else
5309 adev->screen_off = true;
5310 }
5311
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005312 ret = str_parms_get_int(parms, "rotation", &val);
5313 if (ret >= 0) {
5314 bool reverse_speakers = false;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005315 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005316 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005317 // FIXME: note that the code below assumes that the speakers are in the correct placement
5318 // relative to the user when the device is rotated 90deg from its default rotation. This
5319 // assumption is device-specific, not platform-specific like this code.
5320 case 270:
5321 reverse_speakers = true;
Eric Laurent5f4ca952018-10-19 17:33:43 -07005322 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005323 break;
5324 case 0:
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005325 case 180:
Eric Laurent5f4ca952018-10-19 17:33:43 -07005326 camera_rotation = CAMERA_ROTATION_PORTRAIT;
5327 break;
5328 case 90:
5329 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005330 break;
5331 default:
5332 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07005333 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005334 }
Eric Laurent03f09432014-03-25 18:09:11 -07005335 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07005336 // check and set swap
5337 // - check if orientation changed and speaker active
5338 // - set rotation and cache the rotation value
Eric Laurent5f4ca952018-10-19 17:33:43 -07005339 adev->camera_orientation =
5340 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
5341#ifndef MAXXAUDIO_QDSP_ENABLED
vivek mehtae59cfb22017-06-16 15:57:11 -07005342 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Eric Laurent5f4ca952018-10-19 17:33:43 -07005343#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005344 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07005345 }
5346
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005347 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
5348 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005349 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005350 }
5351
David Linee3fe402017-03-13 10:00:42 -07005352 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
5353 if (ret >= 0) {
5354 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005355 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005356 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5357 if (ret >= 0) {
5358 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005359 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005360 }
Eric Laurent99dab492017-06-17 15:19:08 -07005361 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005362 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5363 if (ret >= 0) {
5364 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005365 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005366 }
5367 }
5368 }
5369
5370 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
5371 if (ret >= 0) {
5372 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07005373 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005374 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5375 if (ret >= 0) {
5376 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005377 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005378 }
Eric Laurent99dab492017-06-17 15:19:08 -07005379 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07005380 ret = str_parms_get_str(parms, "card", value, sizeof(value));
5381 if (ret >= 0) {
5382 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07005383 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07005384 }
5385 }
5386 }
5387
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08005388 audio_extn_hfp_set_parameters(adev, parms);
jasmine cha270b7762018-03-30 15:41:33 +08005389 audio_extn_ma_set_parameters(adev, parms);
5390
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005391 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
5392 if (status >= 0 && a2dp_reconfig) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005393 struct audio_usecase *usecase;
5394 struct listnode *node;
5395 list_for_each(node, &adev->usecase_list) {
5396 usecase = node_to_item(node, struct audio_usecase, list);
5397 if ((usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005398 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005399 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
5400
5401 pthread_mutex_unlock(&adev->lock);
5402 lock_output_stream(usecase->stream.out);
5403 pthread_mutex_lock(&adev->lock);
5404 audio_extn_a2dp_set_handoff_mode(true);
5405 // force device switch to reconfigure encoder
5406 select_devices(adev, usecase->id);
5407 audio_extn_a2dp_set_handoff_mode(false);
5408 pthread_mutex_unlock(&usecase->stream.out->lock);
5409 break;
5410 }
5411 }
5412 }
5413
Eric Laurent5f4ca952018-10-19 17:33:43 -07005414 //FIXME: to be replaced by proper video capture properties API
5415 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
5416 if (ret >= 0) {
5417 int camera_facing = CAMERA_FACING_BACK;
5418 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
5419 camera_facing = CAMERA_FACING_FRONT;
5420 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
5421 camera_facing = CAMERA_FACING_BACK;
5422 else {
5423 ALOGW("%s: invalid camera facing value: %s", __func__, value);
5424 goto done;
5425 }
5426 adev->camera_orientation =
5427 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
5428 struct audio_usecase *usecase;
5429 struct listnode *node;
5430 list_for_each(node, &adev->usecase_list) {
5431 usecase = node_to_item(node, struct audio_usecase, list);
5432 struct stream_in *in = usecase->stream.in;
5433 if (usecase->type == PCM_CAPTURE && in != NULL &&
5434 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
5435 select_devices(adev, in->usecase);
5436 }
5437 }
5438 }
5439
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005440done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005441 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005442 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07005443 ALOGV("%s: exit with code(%d)", __func__, status);
5444 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005445}
5446
5447static char* adev_get_parameters(const struct audio_hw_device *dev,
5448 const char *keys)
5449{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005450 struct audio_device *adev = (struct audio_device *)dev;
5451 struct str_parms *reply = str_parms_create();
5452 struct str_parms *query = str_parms_create_str(keys);
5453 char *str;
5454
5455 pthread_mutex_lock(&adev->lock);
5456
5457 voice_get_parameters(adev, query, reply);
Aniket Kumar Latad6834ef2018-04-06 17:02:48 -07005458 audio_extn_a2dp_get_parameters(query, reply);
5459
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005460 str = str_parms_to_str(reply);
5461 str_parms_destroy(query);
5462 str_parms_destroy(reply);
5463
5464 pthread_mutex_unlock(&adev->lock);
5465 ALOGV("%s: exit: returns - %s", __func__, str);
5466 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467}
5468
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005469static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005470{
5471 return 0;
5472}
5473
Haynes Mathew George5191a852013-09-11 14:19:36 -07005474static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
5475{
5476 int ret;
5477 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005478
Eric Laurent4cc4ce12014-09-10 13:21:01 -05005479 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
5480
Haynes Mathew George5191a852013-09-11 14:19:36 -07005481 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005482 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07005483 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005484
Haynes Mathew George5191a852013-09-11 14:19:36 -07005485 return ret;
5486}
5487
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005488static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005489{
5490 return -ENOSYS;
5491}
5492
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005493static int adev_get_master_volume(struct audio_hw_device *dev __unused,
5494 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495{
5496 return -ENOSYS;
5497}
5498
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005499static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005500{
5501 return -ENOSYS;
5502}
5503
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005504static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005505{
5506 return -ENOSYS;
5507}
5508
5509static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
5510{
5511 struct audio_device *adev = (struct audio_device *)dev;
5512
5513 pthread_mutex_lock(&adev->lock);
5514 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07005515 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005516 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005517 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
5518 voice_is_in_call(adev)) {
5519 voice_stop_call(adev);
5520 adev->current_call_output = NULL;
HW Leef88584d2019-03-18 17:27:18 +08005521
5522 /*
5523 * After stopping the call, it must check if any active capture
5524 * activity device needs to be re-selected.
5525 */
5526 struct audio_usecase *usecase;
5527 struct listnode *node;
5528 list_for_each(node, &adev->usecase_list) {
5529 usecase = node_to_item(node, struct audio_usecase, list);
5530 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL) {
5531 select_devices_with_force_switch(adev, usecase->id, true);
5532 }
5533 }
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07005534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005535 }
5536 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05005537
5538 audio_extn_extspk_set_mode(adev->extspk, mode);
5539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005540 return 0;
5541}
5542
5543static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
5544{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005545 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005546 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005547
Eric Laurent2bafff12016-03-17 12:17:23 -07005548 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005549 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005550 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
5551 ret = audio_extn_hfp_set_mic_mute(adev, state);
5552 } else {
5553 ret = voice_set_mic_mute(adev, state);
5554 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07005555 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00005556 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005557
5558 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005559}
5560
5561static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
5562{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005563 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005564 return 0;
5565}
5566
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005567static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568 const struct audio_config *config)
5569{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07005570 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571
Eric Laurent74b55762017-07-09 17:04:53 -07005572 /* Don't know if USB HIFI in this context so use true to be conservative */
5573 if (check_input_parameters(config->sample_rate, config->format, channel_count,
5574 true /*is_usb_hifi */) != 0)
5575 return 0;
5576
vivek mehtaa68fea62017-06-08 19:04:02 -07005577 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5578 config->sample_rate, config->format,
5579 channel_count,
5580 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005581}
5582
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005583static bool adev_input_allow_hifi_record(struct audio_device *adev,
5584 audio_devices_t devices,
5585 audio_input_flags_t flags,
5586 audio_source_t source) {
5587 const bool allowed = true;
5588
5589 if (!audio_is_usb_in_device(devices))
5590 return !allowed;
5591
5592 switch (flags) {
5593 case AUDIO_INPUT_FLAG_NONE:
5594 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
5595 break;
5596 default:
5597 return !allowed;
5598 }
5599
5600 switch (source) {
5601 case AUDIO_SOURCE_DEFAULT:
5602 case AUDIO_SOURCE_MIC:
5603 case AUDIO_SOURCE_UNPROCESSED:
5604 break;
5605 default:
5606 return !allowed;
5607 }
5608
5609 switch (adev->mode) {
5610 case 0:
5611 break;
5612 default:
5613 return !allowed;
5614 }
5615
5616 return allowed;
5617}
5618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005619static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005620 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005621 audio_devices_t devices,
5622 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005623 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07005624 audio_input_flags_t flags,
5625 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05005626 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005627{
5628 struct audio_device *adev = (struct audio_device *)dev;
5629 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005630 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07005631 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005632 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005633 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005634 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
5635 devices,
5636 flags,
5637 source);
Andy Hung88ce1d92018-10-29 18:31:12 -07005638 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
5639 " sample_rate %u, channel_mask %#x, format %#x",
5640 __func__, flags, is_usb_dev, may_use_hifi_record,
5641 config->sample_rate, config->channel_mask, config->format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005642 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005643
Andy Hungd9653bd2017-08-01 19:31:39 -07005644 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
5645 return -ENOSYS;
5646 }
5647
Eric Laurent74b55762017-07-09 17:04:53 -07005648 if (!(is_usb_dev && may_use_hifi_record)) {
5649 if (config->sample_rate == 0)
5650 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
5651 if (config->channel_mask == AUDIO_CHANNEL_NONE)
5652 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5653 if (config->format == AUDIO_FORMAT_DEFAULT)
5654 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005655
Eric Laurent74b55762017-07-09 17:04:53 -07005656 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
5657
5658 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
5659 return -EINVAL;
5660 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005661
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005662 if (audio_extn_tfa_98xx_is_supported() &&
5663 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005664 return -EINVAL;
5665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005666 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
5667
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005668 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07005669 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005671 in->stream.common.get_sample_rate = in_get_sample_rate;
5672 in->stream.common.set_sample_rate = in_set_sample_rate;
5673 in->stream.common.get_buffer_size = in_get_buffer_size;
5674 in->stream.common.get_channels = in_get_channels;
5675 in->stream.common.get_format = in_get_format;
5676 in->stream.common.set_format = in_set_format;
5677 in->stream.common.standby = in_standby;
5678 in->stream.common.dump = in_dump;
5679 in->stream.common.set_parameters = in_set_parameters;
5680 in->stream.common.get_parameters = in_get_parameters;
5681 in->stream.common.add_audio_effect = in_add_audio_effect;
5682 in->stream.common.remove_audio_effect = in_remove_audio_effect;
5683 in->stream.set_gain = in_set_gain;
5684 in->stream.read = in_read;
5685 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08005686 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07005687 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLean57530d52018-12-17 08:24:21 -07005688 in->stream.set_microphone_direction = in_set_microphone_direction;
5689 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchenba338cd2019-01-21 11:57:17 +08005690 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005691
5692 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005693 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005694 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005695 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005696 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005697 in->flags = flags;
justinwengc6347db2019-02-21 18:49:00 +08005698 in->direction = MIC_DIRECTION_UNSPECIFIED;
5699 in->zoom = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005700
Andy Hung88ce1d92018-10-29 18:31:12 -07005701 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Arun Mirpuriba2749a2018-04-17 14:32:24 -07005702 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
5703 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
5704 /* Force channel config requested to mono if incall
5705 record is being requested for only uplink/downlink */
5706 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
5707 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
5708 ret = -EINVAL;
5709 goto err_open;
5710 }
5711 }
5712
Haynes Mathew George569b7482017-05-08 14:44:27 -07005713 if (is_usb_dev && may_use_hifi_record) {
5714 /* HiFi record selects an appropriate format, channel, rate combo
5715 depending on sink capabilities*/
5716 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
5717 &config->format,
5718 &in->supported_formats[0],
5719 MAX_SUPPORTED_FORMATS,
5720 &config->channel_mask,
5721 &in->supported_channel_masks[0],
5722 MAX_SUPPORTED_CHANNEL_MASKS,
5723 &config->sample_rate,
5724 &in->supported_sample_rates[0],
5725 MAX_SUPPORTED_SAMPLE_RATES);
5726 if (ret != 0) {
5727 ret = -EINVAL;
5728 goto err_open;
5729 }
Eric Laurent74b55762017-07-09 17:04:53 -07005730 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005731 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07005732 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07005733 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
5734 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
5735 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
5736 bool ret_error = false;
5737 /* 24 bit is restricted to UNPROCESSED source only,also format supported
5738 from HAL is 8_24
5739 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
5740 8_24 return error indicating supported format is 8_24
5741 *> In case of any other source requesting 24 bit or float return error
5742 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07005743
vivek mehta57ff9b52016-04-28 14:13:08 -07005744 on error flinger will retry with supported format passed
5745 */
juyuchenbe5c67e2018-08-29 17:19:20 +08005746 if (!is_supported_24bits_audiosource(source)) {
vivek mehta57ff9b52016-04-28 14:13:08 -07005747 config->format = AUDIO_FORMAT_PCM_16_BIT;
5748 ret_error = true;
5749 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
5750 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
5751 ret_error = true;
5752 }
5753
5754 if (ret_error) {
5755 ret = -EINVAL;
5756 goto err_open;
5757 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005758 }
5759
vivek mehta57ff9b52016-04-28 14:13:08 -07005760 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07005761 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07005762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005763 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005764 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
5765 if (config->sample_rate == 0)
5766 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5767 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
5768 config->sample_rate != 8000) {
5769 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
5770 ret = -EINVAL;
5771 goto err_open;
5772 }
vivek mehta4ed66e62016-04-15 23:33:34 -07005773
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005774 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
5775 config->format = AUDIO_FORMAT_PCM_16_BIT;
5776 ret = -EINVAL;
5777 goto err_open;
5778 }
5779
5780 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
5781 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07005782 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07005783 } else if (is_usb_dev && may_use_hifi_record) {
5784 in->usecase = USECASE_AUDIO_RECORD_HIFI;
5785 in->config = pcm_config_audio_capture;
5786 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005787 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5788 config->sample_rate,
5789 config->format,
5790 channel_count,
5791 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07005792 in->config.period_size = buffer_size / frame_size;
5793 in->config.rate = config->sample_rate;
5794 in->af_period_multiplier = 1;
5795 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005796 } else {
5797 in->usecase = USECASE_AUDIO_RECORD;
5798 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08005799 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005800 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07005801#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07005802 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07005803#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08005804 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005805 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08005806 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005807 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005808 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5809 config->sample_rate,
5810 config->format,
5811 channel_count,
5812 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08005813 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005814 in->config.rate = config->sample_rate;
5815 in->af_period_multiplier = 1;
5816 } else {
5817 // period size is left untouched for rt mode playback
5818 in->config = pcm_config_audio_capture_rt;
5819 in->af_period_multiplier = af_period_multiplier;
5820 }
5821 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
5822 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07005823 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08005824 in->usecase = USECASE_AUDIO_RECORD_MMAP;
5825 in->config = pcm_config_mmap_capture;
5826 in->stream.start = in_start;
5827 in->stream.stop = in_stop;
5828 in->stream.create_mmap_buffer = in_create_mmap_buffer;
5829 in->stream.get_mmap_position = in_get_mmap_position;
5830 in->af_period_multiplier = 1;
5831 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07005832 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07005833 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07005834 (config->sample_rate == 8000 ||
5835 config->sample_rate == 16000 ||
5836 config->sample_rate == 32000 ||
5837 config->sample_rate == 48000) &&
5838 channel_count == 1) {
5839 in->usecase = USECASE_AUDIO_RECORD_VOIP;
5840 in->config = pcm_config_audio_capture;
5841 frame_size = audio_stream_in_frame_size(&in->stream);
5842 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
5843 config->sample_rate,
5844 config->format,
5845 channel_count, false /*is_low_latency*/);
5846 in->config.period_size = buffer_size / frame_size;
5847 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
5848 in->config.rate = config->sample_rate;
5849 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005850 } else {
5851 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005852 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07005853 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
5854 config->sample_rate,
5855 config->format,
5856 channel_count,
5857 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08005858 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005859 in->config.rate = config->sample_rate;
5860 in->af_period_multiplier = 1;
5861 }
5862 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
5863 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07005864 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08005865
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005866 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07005867 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005868
Kevin Rocarda325aa22018-04-03 09:15:52 -07005869
5870 register_format(in->format, in->supported_formats);
5871 register_channel_mask(in->channel_mask, in->supported_channel_masks);
5872 register_sample_rate(in->sample_rate, in->supported_sample_rates);
5873
Andy Hungd13f0d32017-06-12 13:58:37 -07005874 in->error_log = error_log_create(
5875 ERROR_LOG_ENTRIES,
5876 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
5877
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07005878 /* This stream could be for sound trigger lab,
5879 get sound trigger pcm if present */
5880 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005881
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005882 lock_input_stream(in);
5883 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5884 pthread_mutex_lock(&adev->lock);
5885 in->card_status = adev->card_status;
5886 pthread_mutex_unlock(&adev->lock);
5887 pthread_mutex_unlock(&in->lock);
5888
vivek mehta4a824772017-06-08 19:05:49 -07005889 stream_app_type_cfg_init(&in->app_type_cfg);
5890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005891 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005892 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005893 return 0;
5894
5895err_open:
5896 free(in);
5897 *stream_in = NULL;
5898 return ret;
5899}
5900
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005901static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005902 struct audio_stream_in *stream)
5903{
Andy Hungd13f0d32017-06-12 13:58:37 -07005904 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005905 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005906
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005907 // must deregister from sndmonitor first to prevent races
5908 // between the callback and close_stream
5909 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005910 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005911
5912 error_log_destroy(in->error_log);
5913 in->error_log = NULL;
5914
Andy Hung0dbb52b2017-08-09 13:51:38 -07005915 pthread_mutex_destroy(&in->pre_lock);
5916 pthread_mutex_destroy(&in->lock);
5917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005918 free(stream);
5919
5920 return;
5921}
5922
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005923static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005924{
5925 return 0;
5926}
5927
Andy Hung31aca912014-03-20 17:14:59 -07005928/* verifies input and output devices and their capabilities.
5929 *
5930 * This verification is required when enabling extended bit-depth or
5931 * sampling rates, as not all qcom products support it.
5932 *
5933 * Suitable for calling only on initialization such as adev_open().
5934 * It fills the audio_device use_case_table[] array.
5935 *
5936 * Has a side-effect that it needs to configure audio routing / devices
5937 * in order to power up the devices and read the device parameters.
5938 * It does not acquire any hw device lock. Should restore the devices
5939 * back to "normal state" upon completion.
5940 */
5941static int adev_verify_devices(struct audio_device *adev)
5942{
5943 /* enumeration is a bit difficult because one really wants to pull
5944 * the use_case, device id, etc from the hidden pcm_device_table[].
5945 * In this case there are the following use cases and device ids.
5946 *
5947 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5948 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005949 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005950 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5951 * [USECASE_AUDIO_RECORD] = {0, 0},
5952 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5953 * [USECASE_VOICE_CALL] = {2, 2},
5954 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005955 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005956 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5957 */
5958
5959 /* should be the usecases enabled in adev_open_input_stream() */
5960 static const int test_in_usecases[] = {
5961 USECASE_AUDIO_RECORD,
5962 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5963 };
5964 /* should be the usecases enabled in adev_open_output_stream()*/
5965 static const int test_out_usecases[] = {
5966 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5967 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5968 };
5969 static const usecase_type_t usecase_type_by_dir[] = {
5970 PCM_PLAYBACK,
5971 PCM_CAPTURE,
5972 };
5973 static const unsigned flags_by_dir[] = {
5974 PCM_OUT,
5975 PCM_IN,
5976 };
5977
5978 size_t i;
5979 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005980 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005981 char info[512]; /* for possible debug info */
5982
5983 for (dir = 0; dir < 2; ++dir) {
5984 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5985 const unsigned flags_dir = flags_by_dir[dir];
5986 const size_t testsize =
5987 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5988 const int *testcases =
5989 dir ? test_in_usecases : test_out_usecases;
5990 const audio_devices_t audio_device =
5991 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5992
5993 for (i = 0; i < testsize; ++i) {
5994 const audio_usecase_t audio_usecase = testcases[i];
5995 int device_id;
5996 snd_device_t snd_device;
5997 struct pcm_params **pparams;
5998 struct stream_out out;
5999 struct stream_in in;
6000 struct audio_usecase uc_info;
6001 int retval;
6002
6003 pparams = &adev->use_case_table[audio_usecase];
6004 pcm_params_free(*pparams); /* can accept null input */
6005 *pparams = NULL;
6006
6007 /* find the device ID for the use case (signed, for error) */
6008 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
6009 if (device_id < 0)
6010 continue;
6011
6012 /* prepare structures for device probing */
6013 memset(&uc_info, 0, sizeof(uc_info));
6014 uc_info.id = audio_usecase;
6015 uc_info.type = usecase_type;
6016 if (dir) {
Andy Hung31aca912014-03-20 17:14:59 -07006017 memset(&in, 0, sizeof(in));
6018 in.device = audio_device;
6019 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
6020 uc_info.stream.in = &in;
Andy Hung31aca912014-03-20 17:14:59 -07006021 }
6022 memset(&out, 0, sizeof(out));
6023 out.devices = audio_device; /* only field needed in select_devices */
6024 uc_info.stream.out = &out;
6025 uc_info.devices = audio_device;
6026 uc_info.in_snd_device = SND_DEVICE_NONE;
6027 uc_info.out_snd_device = SND_DEVICE_NONE;
6028 list_add_tail(&adev->usecase_list, &uc_info.list);
6029
6030 /* select device - similar to start_(in/out)put_stream() */
6031 retval = select_devices(adev, audio_usecase);
6032 if (retval >= 0) {
6033 *pparams = pcm_params_get(card_id, device_id, flags_dir);
6034#if LOG_NDEBUG == 0
6035 if (*pparams) {
6036 ALOGV("%s: (%s) card %d device %d", __func__,
6037 dir ? "input" : "output", card_id, device_id);
6038 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07006039 } else {
6040 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
6041 }
6042#endif
6043 }
6044
6045 /* deselect device - similar to stop_(in/out)put_stream() */
6046 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07006047 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07006048 /* 2. Disable the rx device */
6049 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07006050 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07006051 list_remove(&uc_info.list);
6052 }
6053 }
Andy Hung31aca912014-03-20 17:14:59 -07006054 return 0;
6055}
6056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006057static int adev_close(hw_device_t *device)
6058{
Andy Hung31aca912014-03-20 17:14:59 -07006059 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006060 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006061
6062 if (!adev)
6063 return 0;
6064
6065 pthread_mutex_lock(&adev_init_lock);
6066
6067 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006068 audio_extn_snd_mon_unregister_listener(adev);
6069 audio_extn_tfa_98xx_deinit();
jasmine cha270b7762018-03-30 15:41:33 +08006070 audio_extn_ma_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006071 audio_route_free(adev->audio_route);
6072 free(adev->snd_dev_ref_cnt);
6073 platform_deinit(adev->platform);
6074 audio_extn_extspk_deinit(adev->extspk);
6075 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006076 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07006077 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
6078 pcm_params_free(adev->use_case_table[i]);
6079 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006080 if (adev->adm_deinit)
6081 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07006082 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006083 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07006084 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07006085
6086 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006088 return 0;
6089}
6090
Glenn Kasten4f993392014-05-14 07:30:48 -07006091/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
6092 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
6093 * just that it _might_ work.
6094 */
6095static int period_size_is_plausible_for_low_latency(int period_size)
6096{
6097 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006098 case 48:
6099 case 96:
6100 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07006101 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07006102 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07006103 case 240:
6104 case 320:
6105 case 480:
6106 return 1;
6107 default:
6108 return 0;
6109 }
6110}
6111
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006112static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
6113{
6114 int card;
6115 card_status_t status;
6116
6117 if (!parms)
6118 return;
6119
6120 if (parse_snd_card_status(parms, &card, &status) < 0)
6121 return;
6122
6123 pthread_mutex_lock(&adev->lock);
6124 bool valid_cb = (card == adev->snd_card);
6125 if (valid_cb) {
6126 if (adev->card_status != status) {
6127 adev->card_status = status;
6128 platform_snd_card_update(adev->platform, status);
6129 }
6130 }
6131 pthread_mutex_unlock(&adev->lock);
6132 return;
6133}
6134
Aniket Kumar Lata26483012018-01-31 20:21:42 -08006135/* out and adev lock held */
6136static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
6137{
6138 struct audio_usecase *uc_info;
6139 float left_p;
6140 float right_p;
6141 audio_devices_t devices;
6142
6143 uc_info = get_usecase_from_list(adev, out->usecase);
6144 if (uc_info == NULL) {
6145 ALOGE("%s: Could not find the usecase (%d) in the list",
6146 __func__, out->usecase);
6147 return -EINVAL;
6148 }
6149
6150 ALOGD("%s: enter: usecase(%d: %s)", __func__,
6151 out->usecase, use_case_table[out->usecase]);
6152
6153 if (restore) {
6154 // restore A2DP device for active usecases and unmute if required
6155 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
6156 !is_a2dp_device(uc_info->out_snd_device)) {
6157 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
6158 select_devices(adev, uc_info->id);
6159 pthread_mutex_lock(&out->compr_mute_lock);
6160 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6161 (out->a2dp_compress_mute)) {
6162 out->a2dp_compress_mute = false;
6163 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
6164 }
6165 pthread_mutex_unlock(&out->compr_mute_lock);
6166 }
6167 } else {
6168 // mute compress stream if suspended
6169 pthread_mutex_lock(&out->compr_mute_lock);
6170 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
6171 (!out->a2dp_compress_mute)) {
6172 if (!out->standby) {
6173 ALOGD("%s: selecting speaker and muting stream", __func__);
6174 devices = out->devices;
6175 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
6176 left_p = out->volume_l;
6177 right_p = out->volume_r;
6178 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6179 compress_pause(out->compr);
6180 set_compr_volume(&out->stream, 0.0f, 0.0f);
6181 out->a2dp_compress_mute = true;
6182 select_devices(adev, out->usecase);
6183 if (out->offload_state == OFFLOAD_STATE_PLAYING)
6184 compress_resume(out->compr);
6185 out->devices = devices;
6186 out->volume_l = left_p;
6187 out->volume_r = right_p;
6188 }
6189 }
6190 pthread_mutex_unlock(&out->compr_mute_lock);
6191 }
6192 ALOGV("%s: exit", __func__);
6193 return 0;
6194}
6195
6196int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
6197{
6198 int ret = 0;
6199
6200 lock_output_stream(out);
6201 pthread_mutex_lock(&adev->lock);
6202
6203 ret = check_a2dp_restore_l(adev, out, restore);
6204
6205 pthread_mutex_unlock(&adev->lock);
6206 pthread_mutex_unlock(&out->lock);
6207 return ret;
6208}
6209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006210static int adev_open(const hw_module_t *module, const char *name,
6211 hw_device_t **device)
6212{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07006213 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214
Eric Laurent2bafff12016-03-17 12:17:23 -07006215 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006216 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006217 pthread_mutex_lock(&adev_init_lock);
6218 if (audio_device_ref_count != 0) {
6219 *device = &adev->device.common;
6220 audio_device_ref_count++;
6221 ALOGV("%s: returning existing instance of adev", __func__);
6222 ALOGV("%s: exit", __func__);
6223 pthread_mutex_unlock(&adev_init_lock);
6224 return 0;
6225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006226 adev = calloc(1, sizeof(struct audio_device));
6227
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006228 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
6229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006230 adev->device.common.tag = HARDWARE_DEVICE_TAG;
6231 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
6232 adev->device.common.module = (struct hw_module_t *)module;
6233 adev->device.common.close = adev_close;
6234
6235 adev->device.init_check = adev_init_check;
6236 adev->device.set_voice_volume = adev_set_voice_volume;
6237 adev->device.set_master_volume = adev_set_master_volume;
6238 adev->device.get_master_volume = adev_get_master_volume;
6239 adev->device.set_master_mute = adev_set_master_mute;
6240 adev->device.get_master_mute = adev_get_master_mute;
6241 adev->device.set_mode = adev_set_mode;
6242 adev->device.set_mic_mute = adev_set_mic_mute;
6243 adev->device.get_mic_mute = adev_get_mic_mute;
6244 adev->device.set_parameters = adev_set_parameters;
6245 adev->device.get_parameters = adev_get_parameters;
6246 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
6247 adev->device.open_output_stream = adev_open_output_stream;
6248 adev->device.close_output_stream = adev_close_output_stream;
6249 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08006250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251 adev->device.close_input_stream = adev_close_input_stream;
6252 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07006253 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006254
6255 /* Set the default route before the PCM stream is opened */
6256 pthread_mutex_lock(&adev->lock);
6257 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08006258 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006259 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08006260 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07006261 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07006262 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07006263 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08006264 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006265 pthread_mutex_unlock(&adev->lock);
6266
6267 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07006268 adev->platform = platform_init(adev);
6269 if (!adev->platform) {
6270 free(adev->snd_dev_ref_cnt);
6271 free(adev);
6272 ALOGE("%s: Failed to init platform data, aborting.", __func__);
6273 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006274 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07006275 return -EINVAL;
6276 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05006277 adev->extspk = audio_extn_extspk_init(adev);
6278
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006279 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
6280 if (adev->visualizer_lib == NULL) {
6281 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
6282 } else {
6283 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
6284 adev->visualizer_start_output =
Aniket Kumar Lata90c36462018-04-06 13:56:37 -07006285 (int (*)(audio_io_handle_t, int, int, int))dlsym(adev->visualizer_lib,
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006286 "visualizer_hal_start_output");
6287 adev->visualizer_stop_output =
6288 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
6289 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07006290 }
6291
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006292 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
6293 if (adev->offload_effects_lib == NULL) {
6294 ALOGW("%s: DLOPEN failed for %s", __func__,
6295 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6296 } else {
6297 ALOGV("%s: DLOPEN successful for %s", __func__,
6298 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
6299 adev->offload_effects_start_output =
6300 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6301 "offload_effects_bundle_hal_start_output");
6302 adev->offload_effects_stop_output =
6303 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
6304 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07006305 }
6306
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07006307 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
6308 if (adev->adm_lib == NULL) {
6309 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
6310 } else {
6311 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
6312 adev->adm_init = (adm_init_t)
6313 dlsym(adev->adm_lib, "adm_init");
6314 adev->adm_deinit = (adm_deinit_t)
6315 dlsym(adev->adm_lib, "adm_deinit");
6316 adev->adm_register_input_stream = (adm_register_input_stream_t)
6317 dlsym(adev->adm_lib, "adm_register_input_stream");
6318 adev->adm_register_output_stream = (adm_register_output_stream_t)
6319 dlsym(adev->adm_lib, "adm_register_output_stream");
6320 adev->adm_deregister_stream = (adm_deregister_stream_t)
6321 dlsym(adev->adm_lib, "adm_deregister_stream");
6322 adev->adm_request_focus = (adm_request_focus_t)
6323 dlsym(adev->adm_lib, "adm_request_focus");
6324 adev->adm_abandon_focus = (adm_abandon_focus_t)
6325 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08006326 adev->adm_set_config = (adm_set_config_t)
6327 dlsym(adev->adm_lib, "adm_set_config");
6328 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
6329 dlsym(adev->adm_lib, "adm_request_focus_v2");
6330 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
6331 dlsym(adev->adm_lib, "adm_is_noirq_avail");
6332 adev->adm_on_routing_change = (adm_on_routing_change_t)
6333 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006334 }
6335
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006336 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05006337 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07006338
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006339 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07006340
Andy Hung31aca912014-03-20 17:14:59 -07006341 if (k_enable_extended_precision)
6342 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006343
Glenn Kasten4f993392014-05-14 07:30:48 -07006344 char value[PROPERTY_VALUE_MAX];
6345 int trial;
6346 if (property_get("audio_hal.period_size", value, NULL) > 0) {
6347 trial = atoi(value);
6348 if (period_size_is_plausible_for_low_latency(trial)) {
6349 pcm_config_low_latency.period_size = trial;
6350 pcm_config_low_latency.start_threshold = trial / 4;
6351 pcm_config_low_latency.avail_min = trial / 4;
6352 configured_low_latency_capture_period_size = trial;
6353 }
6354 }
6355 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
6356 trial = atoi(value);
6357 if (period_size_is_plausible_for_low_latency(trial)) {
6358 configured_low_latency_capture_period_size = trial;
6359 }
6360 }
6361
Vignesh Kulothunganb6f0a9c2018-03-22 13:50:22 -07006362 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
6363
Eric Laurent5f4ca952018-10-19 17:33:43 -07006364 adev->camera_orientation = CAMERA_DEFAULT;
6365
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08006366 // commented as full set of app type cfg is sent from platform
6367 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07006368 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08006369
6370 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
6371 af_period_multiplier = atoi(value);
6372 if (af_period_multiplier < 0) {
6373 af_period_multiplier = 2;
6374 } else if (af_period_multiplier > 4) {
6375 af_period_multiplier = 4;
6376 }
6377 ALOGV("new period_multiplier = %d", af_period_multiplier);
6378 }
6379
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006380 audio_extn_tfa_98xx_init(adev);
jasmine cha270b7762018-03-30 15:41:33 +08006381 audio_extn_ma_init(adev->platform);
justinwengc6347db2019-02-21 18:49:00 +08006382 audio_extn_audiozoom_init();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08006383
vivek mehta1a9b7c02015-06-25 11:49:38 -07006384 pthread_mutex_unlock(&adev_init_lock);
6385
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07006386 if (adev->adm_init)
6387 adev->adm_data = adev->adm_init();
6388
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006389 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07006390 audio_extn_snd_mon_init();
6391 pthread_mutex_lock(&adev->lock);
6392 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
6393 adev->card_status = CARD_STATUS_ONLINE;
6394 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07006395 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07006396
Eric Laurent2bafff12016-03-17 12:17:23 -07006397 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006398 return 0;
6399}
6400
6401static struct hw_module_methods_t hal_module_methods = {
6402 .open = adev_open,
6403};
6404
6405struct audio_module HAL_MODULE_INFO_SYM = {
6406 .common = {
6407 .tag = HARDWARE_MODULE_TAG,
6408 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
6409 .hal_api_version = HARDWARE_HAL_API_VERSION,
6410 .id = AUDIO_HARDWARE_MODULE_ID,
6411 .name = "QCOM Audio HAL",
6412 .author = "Code Aurora Forum",
6413 .methods = &hal_module_methods,
6414 },
6415};